From 9449c18ac8c130df000283d5d533f4cecf6b3afe Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 8 Aug 2013 14:10:59 -0700 Subject: [PATCH] cmd/api: rewrite using go/types - adjusted test files so that they actually type-check - adjusted go1.txt, go1.1.txt, next.txt - to run, provide build tag: api_tool Fixes #4538. R=bradfitz CC=golang-dev https://golang.org/cl/12300043 --- api/go1.1.txt | 2 + api/go1.txt | 94 +- api/next.txt | 133 ++- src/cmd/api/clone.go | 251 ----- src/cmd/api/goapi.go | 1146 +++++++------------- src/cmd/api/goapi_test.go | 8 +- src/cmd/api/testdata/src/pkg/p1/golden.txt | 13 +- src/cmd/api/testdata/src/pkg/p1/p1.go | 21 +- 8 files changed, 584 insertions(+), 1084 deletions(-) delete mode 100644 src/cmd/api/clone.go diff --git a/api/go1.1.txt b/api/go1.1.txt index 0d0b5e3801..2362a75f9b 100644 --- a/api/go1.1.txt +++ b/api/go1.1.txt @@ -92,6 +92,7 @@ pkg encoding/json, method (Number) String() string pkg encoding/json, type Number string pkg encoding/xml, func EscapeText(io.Writer, []uint8) error pkg encoding/xml, method (*Encoder) Indent(string, string) +pkg encoding/xml, method (Encoder) ReadFrom(io.Reader) (int64, error) pkg encoding/xml, type Decoder struct, DefaultSpace string pkg go/ast, func NewCommentMap(*token.FileSet, Node, []*CommentGroup) CommentMap pkg go/ast, method (CommentMap) Comments() []*CommentGroup @@ -1700,6 +1701,7 @@ pkg testing, method (BenchmarkResult) AllocsPerOp() int64 pkg testing, method (BenchmarkResult) MemString() string pkg testing, type BenchmarkResult struct, MemAllocs uint64 pkg testing, type BenchmarkResult struct, MemBytes uint64 +pkg text/template, method (Template) ErrorContext(parse.Node) (string, string) pkg text/template/parse, const NodeChain NodeType pkg text/template/parse, const NodeNil NodeType pkg text/template/parse, method (*ChainNode) Add(string) diff --git a/api/go1.txt b/api/go1.txt index e934ce5353..0d2e7c6305 100644 --- a/api/go1.txt +++ b/api/go1.txt @@ -391,6 +391,18 @@ pkg crypto/dsa, var ErrInvalidPublicKey error pkg crypto/ecdsa, func GenerateKey(elliptic.Curve, io.Reader) (*PrivateKey, error) pkg crypto/ecdsa, func Sign(io.Reader, *PrivateKey, []uint8) (*big.Int, *big.Int, error) pkg crypto/ecdsa, func Verify(*PublicKey, []uint8, *big.Int, *big.Int) bool +pkg crypto/ecdsa, method (PrivateKey) Add(*big.Int, *big.Int, *big.Int, *big.Int) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PrivateKey) Double(*big.Int, *big.Int) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PrivateKey) IsOnCurve(*big.Int, *big.Int) bool +pkg crypto/ecdsa, method (PrivateKey) Params() *elliptic.CurveParams +pkg crypto/ecdsa, method (PrivateKey) ScalarBaseMult([]uint8) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PrivateKey) ScalarMult(*big.Int, *big.Int, []uint8) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PublicKey) Add(*big.Int, *big.Int, *big.Int, *big.Int) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PublicKey) Double(*big.Int, *big.Int) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PublicKey) IsOnCurve(*big.Int, *big.Int) bool +pkg crypto/ecdsa, method (PublicKey) Params() *elliptic.CurveParams +pkg crypto/ecdsa, method (PublicKey) ScalarBaseMult([]uint8) (*big.Int, *big.Int) +pkg crypto/ecdsa, method (PublicKey) ScalarMult(*big.Int, *big.Int, []uint8) (*big.Int, *big.Int) pkg crypto/ecdsa, type PrivateKey struct pkg crypto/ecdsa, type PrivateKey struct, D *big.Int pkg crypto/ecdsa, type PrivateKey struct, embedded PublicKey @@ -1614,6 +1626,7 @@ pkg debug/elf, method (NType) GoString() string pkg debug/elf, method (NType) String() string pkg debug/elf, method (OSABI) GoString() string pkg debug/elf, method (OSABI) String() string +pkg debug/elf, method (Prog) ReadAt([]uint8, int64) (int, error) pkg debug/elf, method (ProgFlag) GoString() string pkg debug/elf, method (ProgFlag) String() string pkg debug/elf, method (ProgType) GoString() string @@ -1630,6 +1643,7 @@ pkg debug/elf, method (R_SPARC) GoString() string pkg debug/elf, method (R_SPARC) String() string pkg debug/elf, method (R_X86_64) GoString() string pkg debug/elf, method (R_X86_64) String() string +pkg debug/elf, method (Section) ReadAt([]uint8, int64) (int, error) pkg debug/elf, method (SectionFlag) GoString() string pkg debug/elf, method (SectionFlag) String() string pkg debug/elf, method (SectionIndex) GoString() string @@ -1674,7 +1688,7 @@ pkg debug/elf, type Header32 struct pkg debug/elf, type Header32 struct, Ehsize uint16 pkg debug/elf, type Header32 struct, Entry uint32 pkg debug/elf, type Header32 struct, Flags uint32 -pkg debug/elf, type Header32 struct, Ident [EI_NIDENT]uint8 +pkg debug/elf, type Header32 struct, Ident [16]uint8 pkg debug/elf, type Header32 struct, Machine uint16 pkg debug/elf, type Header32 struct, Phentsize uint16 pkg debug/elf, type Header32 struct, Phnum uint16 @@ -1689,7 +1703,7 @@ pkg debug/elf, type Header64 struct pkg debug/elf, type Header64 struct, Ehsize uint16 pkg debug/elf, type Header64 struct, Entry uint64 pkg debug/elf, type Header64 struct, Flags uint32 -pkg debug/elf, type Header64 struct, Ident [EI_NIDENT]uint8 +pkg debug/elf, type Header64 struct, Ident [16]uint8 pkg debug/elf, type Header64 struct, Machine uint16 pkg debug/elf, type Header64 struct, Phentsize uint16 pkg debug/elf, type Header64 struct, Phnum uint16 @@ -1911,7 +1925,9 @@ pkg debug/macho, method (Dysymtab) Raw() []uint8 pkg debug/macho, method (LoadBytes) Raw() []uint8 pkg debug/macho, method (LoadCmd) GoString() string pkg debug/macho, method (LoadCmd) String() string +pkg debug/macho, method (Section) ReadAt([]uint8, int64) (int, error) pkg debug/macho, method (Segment) Raw() []uint8 +pkg debug/macho, method (Segment) ReadAt([]uint8, int64) (int, error) pkg debug/macho, method (Symtab) Raw() []uint8 pkg debug/macho, type Cpu uint32 pkg debug/macho, type Dylib struct @@ -2154,6 +2170,7 @@ pkg debug/pe, method (*File) Section(string) *Section pkg debug/pe, method (*FormatError) Error() string pkg debug/pe, method (*Section) Data() ([]uint8, error) pkg debug/pe, method (*Section) Open() io.ReadSeeker +pkg debug/pe, method (Section) ReadAt([]uint8, int64) (int, error) pkg debug/pe, type File struct pkg debug/pe, type File struct, Sections []*Section pkg debug/pe, type File struct, embedded FileHeader @@ -2408,6 +2425,13 @@ pkg encoding/xml, method (*UnsupportedTypeError) Error() string pkg encoding/xml, method (CharData) Copy() CharData pkg encoding/xml, method (Comment) Copy() Comment pkg encoding/xml, method (Directive) Copy() Directive +pkg encoding/xml, method (Encoder) Available() int +pkg encoding/xml, method (Encoder) Buffered() int +pkg encoding/xml, method (Encoder) Flush() error +pkg encoding/xml, method (Encoder) Write([]uint8) (int, error) +pkg encoding/xml, method (Encoder) WriteByte(uint8) error +pkg encoding/xml, method (Encoder) WriteRune(int32) (int, error) +pkg encoding/xml, method (Encoder) WriteString(string) (int, error) pkg encoding/xml, method (ProcInst) Copy() ProcInst pkg encoding/xml, method (StartElement) Copy() StartElement pkg encoding/xml, method (UnmarshalError) Error() string @@ -3659,7 +3683,7 @@ pkg image/draw, func Draw(Image, image.Rectangle, image.Image, image.Point, Op) pkg image/draw, func DrawMask(Image, image.Rectangle, image.Image, image.Point, image.Image, image.Point, Op) pkg image/draw, type Image interface { At, Bounds, ColorModel, Set } pkg image/draw, type Image interface, At(int, int) color.Color -pkg image/draw, type Image interface, Bounds() Rectangle +pkg image/draw, type Image interface, Bounds() image.Rectangle pkg image/draw, type Image interface, ColorModel() color.Model pkg image/draw, type Image interface, Set(int, int, color.Color) pkg image/draw, type Op int @@ -4164,7 +4188,7 @@ pkg math, func Trunc(float64) float64 pkg math, func Y0(float64) float64 pkg math, func Y1(float64) float64 pkg math, func Yn(int, float64) float64 -pkg math/big, const MaxBase ideal-int +pkg math/big, const MaxBase ideal-char pkg math/big, func NewInt(int64) *Int pkg math/big, func NewRat(int64, int64) *Rat pkg math/big, method (*Int) Abs(*Int) *Int @@ -5266,6 +5290,14 @@ pkg os/exec, method (*Cmd) StdoutPipe() (io.ReadCloser, error) pkg os/exec, method (*Cmd) Wait() error pkg os/exec, method (*Error) Error() string pkg os/exec, method (*ExitError) Error() string +pkg os/exec, method (ExitError) Exited() bool +pkg os/exec, method (ExitError) Pid() int +pkg os/exec, method (ExitError) String() string +pkg os/exec, method (ExitError) Success() bool +pkg os/exec, method (ExitError) Sys() interface{} +pkg os/exec, method (ExitError) SysUsage() interface{} +pkg os/exec, method (ExitError) SystemTime() time.Duration +pkg os/exec, method (ExitError) UserTime() time.Duration pkg os/exec, type Cmd struct pkg os/exec, type Cmd struct, Args []string pkg os/exec, type Cmd struct, Dir string @@ -5687,6 +5719,7 @@ pkg runtime, type MemProfileRecord struct, Stack0 [32]uintptr pkg runtime, type MemStats struct pkg runtime, type MemStats struct, Alloc uint64 pkg runtime, type MemStats struct, BuckHashSys uint64 +pkg runtime, type MemStats struct, BySize [61]struct pkg runtime, type MemStats struct, DebugGC bool pkg runtime, type MemStats struct, EnableGC bool pkg runtime, type MemStats struct, Frees uint64 @@ -28803,12 +28836,12 @@ pkg syscall (windows-386), type InterfaceInfo struct, BroadcastAddress SockaddrG pkg syscall (windows-386), type InterfaceInfo struct, Flags uint32 pkg syscall (windows-386), type InterfaceInfo struct, Netmask SockaddrGen pkg syscall (windows-386), type IpAdapterInfo struct -pkg syscall (windows-386), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]uint8 -pkg syscall (windows-386), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]uint8 +pkg syscall (windows-386), type IpAdapterInfo struct, AdapterName [260]uint8 +pkg syscall (windows-386), type IpAdapterInfo struct, Address [8]uint8 pkg syscall (windows-386), type IpAdapterInfo struct, AddressLength uint32 pkg syscall (windows-386), type IpAdapterInfo struct, ComboIndex uint32 pkg syscall (windows-386), type IpAdapterInfo struct, CurrentIpAddress *IpAddrString -pkg syscall (windows-386), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]uint8 +pkg syscall (windows-386), type IpAdapterInfo struct, Description [132]uint8 pkg syscall (windows-386), type IpAdapterInfo struct, DhcpEnabled uint32 pkg syscall (windows-386), type IpAdapterInfo struct, DhcpServer IpAddrString pkg syscall (windows-386), type IpAdapterInfo struct, GatewayList IpAddrString @@ -28828,14 +28861,14 @@ pkg syscall (windows-386), type IpAddrString struct, IpMask IpMaskString pkg syscall (windows-386), type IpAddrString struct, Next *IpAddrString pkg syscall (windows-386), type IpAddressString struct pkg syscall (windows-386), type IpAddressString struct, String [16]uint8 -pkg syscall (windows-386), type IpMaskString IpAddressString +pkg syscall (windows-386), type IpMaskString struct pkg syscall (windows-386), type LazyDLL struct pkg syscall (windows-386), type LazyDLL struct, Name string pkg syscall (windows-386), type LazyProc struct pkg syscall (windows-386), type LazyProc struct, Name string pkg syscall (windows-386), type MibIfRow struct pkg syscall (windows-386), type MibIfRow struct, AdminStatus uint32 -pkg syscall (windows-386), type MibIfRow struct, Descr [MAXLEN_IFDESCR]uint8 +pkg syscall (windows-386), type MibIfRow struct, Descr [256]uint8 pkg syscall (windows-386), type MibIfRow struct, DescrLen uint32 pkg syscall (windows-386), type MibIfRow struct, InDiscards uint32 pkg syscall (windows-386), type MibIfRow struct, InErrors uint32 @@ -28846,7 +28879,7 @@ pkg syscall (windows-386), type MibIfRow struct, InUnknownProtos uint32 pkg syscall (windows-386), type MibIfRow struct, Index uint32 pkg syscall (windows-386), type MibIfRow struct, LastChange uint32 pkg syscall (windows-386), type MibIfRow struct, Mtu uint32 -pkg syscall (windows-386), type MibIfRow struct, Name [MAX_INTERFACE_NAME_LEN]uint16 +pkg syscall (windows-386), type MibIfRow struct, Name [256]uint16 pkg syscall (windows-386), type MibIfRow struct, OperStatus uint32 pkg syscall (windows-386), type MibIfRow struct, OutDiscards uint32 pkg syscall (windows-386), type MibIfRow struct, OutErrors uint32 @@ -28854,7 +28887,7 @@ pkg syscall (windows-386), type MibIfRow struct, OutNUcastPkts uint32 pkg syscall (windows-386), type MibIfRow struct, OutOctets uint32 pkg syscall (windows-386), type MibIfRow struct, OutQLen uint32 pkg syscall (windows-386), type MibIfRow struct, OutUcastPkts uint32 -pkg syscall (windows-386), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]uint8 +pkg syscall (windows-386), type MibIfRow struct, PhysAddr [8]uint8 pkg syscall (windows-386), type MibIfRow struct, PhysAddrLen uint32 pkg syscall (windows-386), type MibIfRow struct, Speed uint32 pkg syscall (windows-386), type MibIfRow struct, Type uint32 @@ -28943,7 +28976,7 @@ pkg syscall (windows-386), type Timezoneinformation struct, DaylightName [32]uin pkg syscall (windows-386), type Timezoneinformation struct, StandardBias int32 pkg syscall (windows-386), type Timezoneinformation struct, StandardDate Systemtime pkg syscall (windows-386), type Timezoneinformation struct, StandardName [32]uint16 -pkg syscall (windows-386), type Token Handle +pkg syscall (windows-386), type Token uintptr pkg syscall (windows-386), type Tokenprimarygroup struct pkg syscall (windows-386), type Tokenprimarygroup struct, PrimaryGroup *SID pkg syscall (windows-386), type Tokenuser struct @@ -28962,11 +28995,11 @@ pkg syscall (windows-386), type WSABuf struct pkg syscall (windows-386), type WSABuf struct, Buf *uint8 pkg syscall (windows-386), type WSABuf struct, Len uint32 pkg syscall (windows-386), type WSAData struct -pkg syscall (windows-386), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]uint8 +pkg syscall (windows-386), type WSAData struct, Description [257]uint8 pkg syscall (windows-386), type WSAData struct, HighVersion uint16 pkg syscall (windows-386), type WSAData struct, MaxSockets uint16 pkg syscall (windows-386), type WSAData struct, MaxUdpDg uint16 -pkg syscall (windows-386), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]uint8 +pkg syscall (windows-386), type WSAData struct, SystemStatus [129]uint8 pkg syscall (windows-386), type WSAData struct, VendorInfo *uint8 pkg syscall (windows-386), type WSAData struct, Version uint16 pkg syscall (windows-386), type WaitStatus struct @@ -28982,7 +29015,7 @@ pkg syscall (windows-386), type Win32finddata struct pkg syscall (windows-386), type Win32finddata struct, AlternateFileName [13]uint16 pkg syscall (windows-386), type Win32finddata struct, CreationTime Filetime pkg syscall (windows-386), type Win32finddata struct, FileAttributes uint32 -pkg syscall (windows-386), type Win32finddata struct, FileName [MAX_PATH - 1]uint16 +pkg syscall (windows-386), type Win32finddata struct, FileName [259]uint16 pkg syscall (windows-386), type Win32finddata struct, FileSizeHigh uint32 pkg syscall (windows-386), type Win32finddata struct, FileSizeLow uint32 pkg syscall (windows-386), type Win32finddata struct, LastAccessTime Filetime @@ -29732,12 +29765,12 @@ pkg syscall (windows-amd64), type InterfaceInfo struct, BroadcastAddress Sockadd pkg syscall (windows-amd64), type InterfaceInfo struct, Flags uint32 pkg syscall (windows-amd64), type InterfaceInfo struct, Netmask SockaddrGen pkg syscall (windows-amd64), type IpAdapterInfo struct -pkg syscall (windows-amd64), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]uint8 -pkg syscall (windows-amd64), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]uint8 +pkg syscall (windows-amd64), type IpAdapterInfo struct, AdapterName [260]uint8 +pkg syscall (windows-amd64), type IpAdapterInfo struct, Address [8]uint8 pkg syscall (windows-amd64), type IpAdapterInfo struct, AddressLength uint32 pkg syscall (windows-amd64), type IpAdapterInfo struct, ComboIndex uint32 pkg syscall (windows-amd64), type IpAdapterInfo struct, CurrentIpAddress *IpAddrString -pkg syscall (windows-amd64), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]uint8 +pkg syscall (windows-amd64), type IpAdapterInfo struct, Description [132]uint8 pkg syscall (windows-amd64), type IpAdapterInfo struct, DhcpEnabled uint32 pkg syscall (windows-amd64), type IpAdapterInfo struct, DhcpServer IpAddrString pkg syscall (windows-amd64), type IpAdapterInfo struct, GatewayList IpAddrString @@ -29757,14 +29790,14 @@ pkg syscall (windows-amd64), type IpAddrString struct, IpMask IpMaskString pkg syscall (windows-amd64), type IpAddrString struct, Next *IpAddrString pkg syscall (windows-amd64), type IpAddressString struct pkg syscall (windows-amd64), type IpAddressString struct, String [16]uint8 -pkg syscall (windows-amd64), type IpMaskString IpAddressString +pkg syscall (windows-amd64), type IpMaskString struct pkg syscall (windows-amd64), type LazyDLL struct pkg syscall (windows-amd64), type LazyDLL struct, Name string pkg syscall (windows-amd64), type LazyProc struct pkg syscall (windows-amd64), type LazyProc struct, Name string pkg syscall (windows-amd64), type MibIfRow struct pkg syscall (windows-amd64), type MibIfRow struct, AdminStatus uint32 -pkg syscall (windows-amd64), type MibIfRow struct, Descr [MAXLEN_IFDESCR]uint8 +pkg syscall (windows-amd64), type MibIfRow struct, Descr [256]uint8 pkg syscall (windows-amd64), type MibIfRow struct, DescrLen uint32 pkg syscall (windows-amd64), type MibIfRow struct, InDiscards uint32 pkg syscall (windows-amd64), type MibIfRow struct, InErrors uint32 @@ -29775,7 +29808,7 @@ pkg syscall (windows-amd64), type MibIfRow struct, InUnknownProtos uint32 pkg syscall (windows-amd64), type MibIfRow struct, Index uint32 pkg syscall (windows-amd64), type MibIfRow struct, LastChange uint32 pkg syscall (windows-amd64), type MibIfRow struct, Mtu uint32 -pkg syscall (windows-amd64), type MibIfRow struct, Name [MAX_INTERFACE_NAME_LEN]uint16 +pkg syscall (windows-amd64), type MibIfRow struct, Name [256]uint16 pkg syscall (windows-amd64), type MibIfRow struct, OperStatus uint32 pkg syscall (windows-amd64), type MibIfRow struct, OutDiscards uint32 pkg syscall (windows-amd64), type MibIfRow struct, OutErrors uint32 @@ -29783,7 +29816,7 @@ pkg syscall (windows-amd64), type MibIfRow struct, OutNUcastPkts uint32 pkg syscall (windows-amd64), type MibIfRow struct, OutOctets uint32 pkg syscall (windows-amd64), type MibIfRow struct, OutQLen uint32 pkg syscall (windows-amd64), type MibIfRow struct, OutUcastPkts uint32 -pkg syscall (windows-amd64), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]uint8 +pkg syscall (windows-amd64), type MibIfRow struct, PhysAddr [8]uint8 pkg syscall (windows-amd64), type MibIfRow struct, PhysAddrLen uint32 pkg syscall (windows-amd64), type MibIfRow struct, Speed uint32 pkg syscall (windows-amd64), type MibIfRow struct, Type uint32 @@ -29872,7 +29905,7 @@ pkg syscall (windows-amd64), type Timezoneinformation struct, DaylightName [32]u pkg syscall (windows-amd64), type Timezoneinformation struct, StandardBias int32 pkg syscall (windows-amd64), type Timezoneinformation struct, StandardDate Systemtime pkg syscall (windows-amd64), type Timezoneinformation struct, StandardName [32]uint16 -pkg syscall (windows-amd64), type Token Handle +pkg syscall (windows-amd64), type Token uintptr pkg syscall (windows-amd64), type Tokenprimarygroup struct pkg syscall (windows-amd64), type Tokenprimarygroup struct, PrimaryGroup *SID pkg syscall (windows-amd64), type Tokenuser struct @@ -29891,11 +29924,11 @@ pkg syscall (windows-amd64), type WSABuf struct pkg syscall (windows-amd64), type WSABuf struct, Buf *uint8 pkg syscall (windows-amd64), type WSABuf struct, Len uint32 pkg syscall (windows-amd64), type WSAData struct -pkg syscall (windows-amd64), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]uint8 +pkg syscall (windows-amd64), type WSAData struct, Description [257]uint8 pkg syscall (windows-amd64), type WSAData struct, HighVersion uint16 pkg syscall (windows-amd64), type WSAData struct, MaxSockets uint16 pkg syscall (windows-amd64), type WSAData struct, MaxUdpDg uint16 -pkg syscall (windows-amd64), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]uint8 +pkg syscall (windows-amd64), type WSAData struct, SystemStatus [129]uint8 pkg syscall (windows-amd64), type WSAData struct, VendorInfo *uint8 pkg syscall (windows-amd64), type WSAData struct, Version uint16 pkg syscall (windows-amd64), type WaitStatus struct @@ -29911,7 +29944,7 @@ pkg syscall (windows-amd64), type Win32finddata struct pkg syscall (windows-amd64), type Win32finddata struct, AlternateFileName [13]uint16 pkg syscall (windows-amd64), type Win32finddata struct, CreationTime Filetime pkg syscall (windows-amd64), type Win32finddata struct, FileAttributes uint32 -pkg syscall (windows-amd64), type Win32finddata struct, FileName [MAX_PATH - 1]uint16 +pkg syscall (windows-amd64), type Win32finddata struct, FileName [259]uint16 pkg syscall (windows-amd64), type Win32finddata struct, FileSizeHigh uint32 pkg syscall (windows-amd64), type Win32finddata struct, FileSizeLow uint32 pkg syscall (windows-amd64), type Win32finddata struct, LastAccessTime Filetime @@ -30029,7 +30062,7 @@ pkg syscall, const IP_MULTICAST_LOOP ideal-int pkg syscall, const IP_MULTICAST_TTL ideal-int pkg syscall, const IP_TOS ideal-int pkg syscall, const IP_TTL ideal-int -pkg syscall, const ImplementsGetwd bool +pkg syscall, const ImplementsGetwd ideal-bool pkg syscall, const O_APPEND ideal-int pkg syscall, const O_ASYNC ideal-int pkg syscall, const O_CLOEXEC ideal-int @@ -30596,7 +30629,7 @@ pkg unicode, const MaxRune ideal-char pkg unicode, const ReplacementChar ideal-char pkg unicode, const TitleCase ideal-int pkg unicode, const UpperCase ideal-int -pkg unicode, const UpperLower ideal-int +pkg unicode, const UpperLower ideal-char pkg unicode, const Version ideal-string pkg unicode, func Is(*RangeTable, int32) bool pkg unicode, func IsControl(int32) bool @@ -30843,8 +30876,3 @@ pkg unicode/utf8, func RuneLen(int32) int pkg unicode/utf8, func RuneStart(uint8) bool pkg unicode/utf8, func Valid([]uint8) bool pkg unicode/utf8, func ValidString(string) bool -pkg unsafe, func Alignof(ArbitraryType) uintptr -pkg unsafe, func Offsetof(ArbitraryType) uintptr -pkg unsafe, func Sizeof(ArbitraryType) uintptr -pkg unsafe, type ArbitraryType int -pkg unsafe, type Pointer *ArbitraryType diff --git a/api/next.txt b/api/next.txt index 8f58e73e68..56fc275374 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,3 +1,7 @@ +pkg archive/zip, func RegisterCompressor(uint16, Compressor) +pkg archive/zip, func RegisterDecompressor(uint16, Decompressor) +pkg archive/zip, type Compressor func(io.Writer) (io.WriteCloser, error) +pkg archive/zip, type Decompressor func(io.Reader) io.ReadCloser pkg container/heap, func Fix(Interface, int) pkg container/list, method (*List) MoveAfter(*Element, *Element) pkg container/list, method (*List) MoveBefore(*Element, *Element) @@ -8,18 +12,18 @@ pkg crypto/cipher, type AEAD interface, NonceSize() int pkg crypto/cipher, type AEAD interface, Open([]uint8, []uint8, []uint8, []uint8) ([]uint8, error) pkg crypto/cipher, type AEAD interface, Overhead() int pkg crypto/cipher, type AEAD interface, Seal([]uint8, []uint8, []uint8, []uint8) []uint8 -pkg crypto/md5, func Sum([]uint8) [Size]uint8 +pkg crypto/md5, func Sum([]uint8) [16]uint8 pkg crypto/rsa, const PSSSaltLengthAuto ideal-int pkg crypto/rsa, const PSSSaltLengthEqualsHash ideal-int pkg crypto/rsa, func SignPSS(io.Reader, *PrivateKey, crypto.Hash, []uint8, *PSSOptions) ([]uint8, error) pkg crypto/rsa, func VerifyPSS(*PublicKey, crypto.Hash, []uint8, []uint8, *PSSOptions) error pkg crypto/rsa, type PSSOptions struct pkg crypto/rsa, type PSSOptions struct, SaltLength int -pkg crypto/sha1, func Sum([]uint8) [Size]uint8 -pkg crypto/sha256, func Sum224([]uint8) [Size224]uint8 -pkg crypto/sha256, func Sum256([]uint8) [Size]uint8 -pkg crypto/sha512, func Sum384([]uint8) [Size384]uint8 -pkg crypto/sha512, func Sum512([]uint8) [Size]uint8 +pkg crypto/sha1, func Sum([]uint8) [20]uint8 +pkg crypto/sha256, func Sum224([]uint8) [28]uint8 +pkg crypto/sha256, func Sum256([]uint8) [32]uint8 +pkg crypto/sha512, func Sum384([]uint8) [48]uint8 +pkg crypto/sha512, func Sum512([]uint8) [64]uint8 pkg crypto/subtle, func ConstantTimeLessOrEq(int, int) int pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 @@ -38,6 +42,7 @@ pkg flag, type Getter interface { Get, Set, String } pkg flag, type Getter interface, Get() interface{} pkg flag, type Getter interface, Set(string) error pkg flag, type Getter interface, String() string +pkg flag, var CommandLine *FlagSet pkg go/ast, type SliceExpr struct, Max Expr pkg go/ast, type TypeAssertExpr struct, Lparen token.Pos pkg go/ast, type TypeAssertExpr struct, Rparen token.Pos @@ -31701,20 +31706,136 @@ pkg syscall (openbsd-amd64-cgo), type WaitStatus uint32 pkg syscall (openbsd-amd64-cgo), var Stderr int pkg syscall (openbsd-amd64-cgo), var Stdin int pkg syscall (openbsd-amd64-cgo), var Stdout int +pkg syscall (windows-386), const BASE_PROTOCOL ideal-int pkg syscall (windows-386), const ERROR_HANDLE_EOF Errno +pkg syscall (windows-386), const FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ideal-int +pkg syscall (windows-386), const FILE_SKIP_SET_EVENT_ON_HANDLE ideal-int +pkg syscall (windows-386), const LAYERED_PROTOCOL ideal-int +pkg syscall (windows-386), const MAX_PROTOCOL_CHAIN ideal-int pkg syscall (windows-386), const NetSetupDomainName ideal-int pkg syscall (windows-386), const NetSetupUnjoined ideal-int pkg syscall (windows-386), const NetSetupUnknownStatus ideal-int pkg syscall (windows-386), const NetSetupWorkgroupName ideal-int +pkg syscall (windows-386), const PFL_HIDDEN ideal-int +pkg syscall (windows-386), const PFL_MATCHES_PROTOCOL_ZERO ideal-int +pkg syscall (windows-386), const PFL_MULTIPLE_PROTO_ENTRIES ideal-int +pkg syscall (windows-386), const PFL_NETWORKDIRECT_PROVIDER ideal-int +pkg syscall (windows-386), const PFL_RECOMMENDED_PROTO_ENTRY ideal-int pkg syscall (windows-386), const PROCESS_TERMINATE ideal-int +pkg syscall (windows-386), const WSAPROTOCOL_LEN ideal-int +pkg syscall (windows-386), const XP1_CONNECTIONLESS ideal-int +pkg syscall (windows-386), const XP1_CONNECT_DATA ideal-int +pkg syscall (windows-386), const XP1_DISCONNECT_DATA ideal-int +pkg syscall (windows-386), const XP1_EXPEDITED_DATA ideal-int +pkg syscall (windows-386), const XP1_GRACEFUL_CLOSE ideal-int +pkg syscall (windows-386), const XP1_GUARANTEED_DELIVERY ideal-int +pkg syscall (windows-386), const XP1_GUARANTEED_ORDER ideal-int +pkg syscall (windows-386), const XP1_IFS_HANDLES ideal-int +pkg syscall (windows-386), const XP1_MESSAGE_ORIENTED ideal-int +pkg syscall (windows-386), const XP1_MULTIPOINT_CONTROL_PLANE ideal-int +pkg syscall (windows-386), const XP1_MULTIPOINT_DATA_PLANE ideal-int +pkg syscall (windows-386), const XP1_PARTIAL_MESSAGE ideal-int +pkg syscall (windows-386), const XP1_PSEUDO_STREAM ideal-int +pkg syscall (windows-386), const XP1_QOS_SUPPORTED ideal-int +pkg syscall (windows-386), const XP1_SAN_SUPPORT_SDP ideal-int +pkg syscall (windows-386), const XP1_SUPPORT_BROADCAST ideal-int +pkg syscall (windows-386), const XP1_SUPPORT_MULTIPOINT ideal-int +pkg syscall (windows-386), const XP1_UNI_RECV ideal-int +pkg syscall (windows-386), const XP1_UNI_SEND ideal-int +pkg syscall (windows-386), func LoadSetFileCompletionNotificationModes() error pkg syscall (windows-386), func NetGetJoinInformation(*uint16, **uint16, *uint32) error +pkg syscall (windows-386), func SetFileCompletionNotificationModes(Handle, uint8) error +pkg syscall (windows-386), func WSAEnumProtocols(*int32, *WSAProtocolInfo, *uint32) (int32, error) +pkg syscall (windows-386), type IpMaskString struct, String [16]uint8 +pkg syscall (windows-386), type WSAProtocolChain struct +pkg syscall (windows-386), type WSAProtocolChain struct, ChainEntries [7]uint32 +pkg syscall (windows-386), type WSAProtocolChain struct, ChainLen int32 +pkg syscall (windows-386), type WSAProtocolInfo struct +pkg syscall (windows-386), type WSAProtocolInfo struct, AddressFamily int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, CatalogEntryId uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, MaxSockAddr int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, MessageSize uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, MinSockAddr int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, NetworkByteOrder int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, Protocol int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ProtocolChain WSAProtocolChain +pkg syscall (windows-386), type WSAProtocolInfo struct, ProtocolMaxOffset int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ProtocolName [256]uint16 +pkg syscall (windows-386), type WSAProtocolInfo struct, ProviderFlags uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ProviderId GUID +pkg syscall (windows-386), type WSAProtocolInfo struct, ProviderReserved uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, SecurityScheme int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ServiceFlags1 uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ServiceFlags2 uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ServiceFlags3 uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, ServiceFlags4 uint32 +pkg syscall (windows-386), type WSAProtocolInfo struct, SocketType int32 +pkg syscall (windows-386), type WSAProtocolInfo struct, Version int32 +pkg syscall (windows-amd64), const BASE_PROTOCOL ideal-int pkg syscall (windows-amd64), const ERROR_HANDLE_EOF Errno +pkg syscall (windows-amd64), const FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ideal-int +pkg syscall (windows-amd64), const FILE_SKIP_SET_EVENT_ON_HANDLE ideal-int +pkg syscall (windows-amd64), const LAYERED_PROTOCOL ideal-int +pkg syscall (windows-amd64), const MAX_PROTOCOL_CHAIN ideal-int pkg syscall (windows-amd64), const NetSetupDomainName ideal-int pkg syscall (windows-amd64), const NetSetupUnjoined ideal-int pkg syscall (windows-amd64), const NetSetupUnknownStatus ideal-int pkg syscall (windows-amd64), const NetSetupWorkgroupName ideal-int +pkg syscall (windows-amd64), const PFL_HIDDEN ideal-int +pkg syscall (windows-amd64), const PFL_MATCHES_PROTOCOL_ZERO ideal-int +pkg syscall (windows-amd64), const PFL_MULTIPLE_PROTO_ENTRIES ideal-int +pkg syscall (windows-amd64), const PFL_NETWORKDIRECT_PROVIDER ideal-int +pkg syscall (windows-amd64), const PFL_RECOMMENDED_PROTO_ENTRY ideal-int pkg syscall (windows-amd64), const PROCESS_TERMINATE ideal-int +pkg syscall (windows-amd64), const WSAPROTOCOL_LEN ideal-int +pkg syscall (windows-amd64), const XP1_CONNECTIONLESS ideal-int +pkg syscall (windows-amd64), const XP1_CONNECT_DATA ideal-int +pkg syscall (windows-amd64), const XP1_DISCONNECT_DATA ideal-int +pkg syscall (windows-amd64), const XP1_EXPEDITED_DATA ideal-int +pkg syscall (windows-amd64), const XP1_GRACEFUL_CLOSE ideal-int +pkg syscall (windows-amd64), const XP1_GUARANTEED_DELIVERY ideal-int +pkg syscall (windows-amd64), const XP1_GUARANTEED_ORDER ideal-int +pkg syscall (windows-amd64), const XP1_IFS_HANDLES ideal-int +pkg syscall (windows-amd64), const XP1_MESSAGE_ORIENTED ideal-int +pkg syscall (windows-amd64), const XP1_MULTIPOINT_CONTROL_PLANE ideal-int +pkg syscall (windows-amd64), const XP1_MULTIPOINT_DATA_PLANE ideal-int +pkg syscall (windows-amd64), const XP1_PARTIAL_MESSAGE ideal-int +pkg syscall (windows-amd64), const XP1_PSEUDO_STREAM ideal-int +pkg syscall (windows-amd64), const XP1_QOS_SUPPORTED ideal-int +pkg syscall (windows-amd64), const XP1_SAN_SUPPORT_SDP ideal-int +pkg syscall (windows-amd64), const XP1_SUPPORT_BROADCAST ideal-int +pkg syscall (windows-amd64), const XP1_SUPPORT_MULTIPOINT ideal-int +pkg syscall (windows-amd64), const XP1_UNI_RECV ideal-int +pkg syscall (windows-amd64), const XP1_UNI_SEND ideal-int +pkg syscall (windows-amd64), func LoadSetFileCompletionNotificationModes() error pkg syscall (windows-amd64), func NetGetJoinInformation(*uint16, **uint16, *uint32) error +pkg syscall (windows-amd64), func SetFileCompletionNotificationModes(Handle, uint8) error +pkg syscall (windows-amd64), func WSAEnumProtocols(*int32, *WSAProtocolInfo, *uint32) (int32, error) +pkg syscall (windows-amd64), type IpMaskString struct, String [16]uint8 +pkg syscall (windows-amd64), type WSAProtocolChain struct +pkg syscall (windows-amd64), type WSAProtocolChain struct, ChainEntries [7]uint32 +pkg syscall (windows-amd64), type WSAProtocolChain struct, ChainLen int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct +pkg syscall (windows-amd64), type WSAProtocolInfo struct, AddressFamily int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, CatalogEntryId uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, MaxSockAddr int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, MessageSize uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, MinSockAddr int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, NetworkByteOrder int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, Protocol int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProtocolChain WSAProtocolChain +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProtocolMaxOffset int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProtocolName [256]uint16 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProviderFlags uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProviderId GUID +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ProviderReserved uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, SecurityScheme int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ServiceFlags1 uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ServiceFlags2 uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ServiceFlags3 uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, ServiceFlags4 uint32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, SocketType int32 +pkg syscall (windows-amd64), type WSAProtocolInfo struct, Version int32 pkg testing, func RegisterCover(Cover) pkg testing, type Cover struct pkg testing, type Cover struct, Blocks map[string][]CoverBlock diff --git a/src/cmd/api/clone.go b/src/cmd/api/clone.go deleted file mode 100644 index 180215f4b9..0000000000 --- a/src/cmd/api/clone.go +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2012 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 main - -import ( - "fmt" - "go/ast" - "log" - "reflect" -) - -const debugClone = false - -// TODO(bradfitz): delete this function (and whole file) once -// http://golang.org/issue/4380 is fixed. -func clone(i interface{}) (cloned interface{}) { - if debugClone { - defer func() { - if !reflect.DeepEqual(i, cloned) { - log.Printf("cloned %T doesn't match: in=%#v out=%#v", i, i, cloned) - } - }() - } - switch v := i.(type) { - case nil: - return nil - case *ast.File: - o := &ast.File{ - Doc: v.Doc, // shallow - Package: v.Package, - Comments: v.Comments, // shallow - Name: v.Name, - Scope: v.Scope, - } - for _, x := range v.Decls { - o.Decls = append(o.Decls, clone(x).(ast.Decl)) - } - for _, x := range v.Imports { - o.Imports = append(o.Imports, clone(x).(*ast.ImportSpec)) - } - for _, x := range v.Unresolved { - o.Unresolved = append(o.Unresolved, x) - } - return o - case *ast.GenDecl: - o := new(ast.GenDecl) - *o = *v - o.Specs = nil - for _, x := range v.Specs { - o.Specs = append(o.Specs, clone(x).(ast.Spec)) - } - return o - case *ast.TypeSpec: - o := new(ast.TypeSpec) - *o = *v - o.Type = cloneExpr(v.Type) - return o - case *ast.InterfaceType: - o := new(ast.InterfaceType) - *o = *v - o.Methods = clone(v.Methods).(*ast.FieldList) - return o - case *ast.FieldList: - if v == nil { - return v - } - o := new(ast.FieldList) - *o = *v - o.List = nil - for _, x := range v.List { - o.List = append(o.List, clone(x).(*ast.Field)) - } - return o - case *ast.Field: - o := &ast.Field{ - Doc: v.Doc, // shallow - Type: cloneExpr(v.Type), - Tag: clone(v.Tag).(*ast.BasicLit), - Comment: v.Comment, // shallow - } - for _, x := range v.Names { - o.Names = append(o.Names, clone(x).(*ast.Ident)) - } - return o - case *ast.FuncType: - if v == nil { - return v - } - return &ast.FuncType{ - Func: v.Func, - Params: clone(v.Params).(*ast.FieldList), - Results: clone(v.Results).(*ast.FieldList), - } - case *ast.FuncDecl: - if v == nil { - return v - } - return &ast.FuncDecl{ - Recv: clone(v.Recv).(*ast.FieldList), - Name: v.Name, - Type: clone(v.Type).(*ast.FuncType), - Body: v.Body, // shallow - } - case *ast.ValueSpec: - if v == nil { - return v - } - o := &ast.ValueSpec{ - Type: cloneExpr(v.Type), - } - for _, x := range v.Names { - o.Names = append(o.Names, x) - } - for _, x := range v.Values { - o.Values = append(o.Values, cloneExpr(x)) - } - return o - case *ast.CallExpr: - if v == nil { - return v - } - o := &ast.CallExpr{} - *o = *v - o.Args = cloneExprs(v.Args) - o.Fun = cloneExpr(v.Fun) - return o - case *ast.SelectorExpr: - if v == nil { - return nil - } - return &ast.SelectorExpr{ - X: cloneExpr(v.X), - Sel: v.Sel, - } - case *ast.ArrayType: - return &ast.ArrayType{ - Lbrack: v.Lbrack, - Len: cloneExpr(v.Len), - Elt: cloneExpr(v.Elt), - } - case *ast.StructType: - return &ast.StructType{ - Struct: v.Struct, - Fields: clone(v.Fields).(*ast.FieldList), - Incomplete: v.Incomplete, - } - case *ast.StarExpr: - return &ast.StarExpr{ - Star: v.Star, - X: cloneExpr(v.X), - } - case *ast.CompositeLit: - return &ast.CompositeLit{ - Type: cloneExpr(v.Type), - Lbrace: v.Lbrace, - Elts: cloneExprs(v.Elts), - Rbrace: v.Rbrace, - } - case *ast.UnaryExpr: - return &ast.UnaryExpr{ - OpPos: v.OpPos, - Op: v.Op, - X: cloneExpr(v.X), - } - case *ast.BinaryExpr: - return &ast.BinaryExpr{ - OpPos: v.OpPos, - Op: v.Op, - X: cloneExpr(v.X), - Y: cloneExpr(v.Y), - } - case *ast.Ellipsis: - return &ast.Ellipsis{ - Ellipsis: v.Ellipsis, - Elt: cloneExpr(v.Elt), - } - case *ast.KeyValueExpr: - return &ast.KeyValueExpr{ - Key: cloneExpr(v.Key), - Colon: v.Colon, - Value: cloneExpr(v.Value), - } - case *ast.FuncLit: - return &ast.FuncLit{ - Type: clone(v.Type).(*ast.FuncType), - Body: v.Body, // shallow - } - case *ast.MapType: - return &ast.MapType{ - Map: v.Map, - Key: cloneExpr(v.Key), - Value: cloneExpr(v.Value), - } - case *ast.ParenExpr: - return &ast.ParenExpr{ - Lparen: v.Lparen, - X: cloneExpr(v.X), - Rparen: v.Rparen, - } - case *ast.Ident, *ast.BasicLit: - return v - case *ast.ImportSpec: - return &ast.ImportSpec{ - Doc: v.Doc, // shallow - Name: v.Name, - Path: clone(v.Path).(*ast.BasicLit), - Comment: v.Comment, // shallow - EndPos: v.EndPos, - } - case *ast.ChanType: - return &ast.ChanType{ - Begin: v.Begin, - Arrow: v.Arrow, - Dir: v.Dir, - Value: cloneExpr(v.Value), - } - case *ast.TypeAssertExpr: - return &ast.TypeAssertExpr{ - X: cloneExpr(v.X), - Type: cloneExpr(v.Type), - } - case *ast.IndexExpr: - return &ast.IndexExpr{ - X: cloneExpr(v.X), - Index: cloneExpr(v.Index), - Lbrack: v.Lbrack, - Rbrack: v.Rbrack, - } - } - panic(fmt.Sprintf("Uncloneable type %T", i)) -} - -func cloneExpr(x ast.Expr) ast.Expr { - if x == nil { - return nil - } - return clone(x).(ast.Expr) -} - -func cloneExprs(x []ast.Expr) []ast.Expr { - if x == nil { - return nil - } - o := make([]ast.Expr, len(x)) - for i, x := range x { - o[i] = cloneExpr(x) - } - return o -} diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 8fa45648b6..1b28628016 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -1,39 +1,33 @@ +// +build api_tool + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Api computes the exported API of a set of Go packages. -// -// BUG(bradfitz): Note that this tool is only currently suitable -// for use on the Go standard library, not arbitrary packages. -// Once the Go AST has type information, this tool will be more -// reliable without hard-coded hacks throughout. +// Binary api computes the exported API of a set of Go packages. package main import ( "bufio" "bytes" - "errors" "flag" "fmt" "go/ast" "go/build" - "go/doc" "go/parser" - "go/printer" "go/token" "io" "io/ioutil" "log" "os" "os/exec" - "path" "path/filepath" "regexp" "runtime" "sort" - "strconv" "strings" + + "code.google.com/p/go.tools/go/types" ) // Flags @@ -130,35 +124,31 @@ func main() { c.Compiler = build.Default.Compiler } - var pkgs []string + var pkgNames []string if flag.NArg() > 0 { - pkgs = flag.Args() + pkgNames = flag.Args() } else { stds, err := exec.Command("go", "list", "std").Output() if err != nil { log.Fatal(err) } - pkgs = strings.Fields(string(stds)) + pkgNames = strings.Fields(string(stds)) } var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true for _, context := range contexts { - w := NewWalker() - w.context = context - - for _, pkg := range pkgs { - w.wantedPkg[pkg] = true - } + w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg")) - for _, pkg := range pkgs { - if strings.HasPrefix(pkg, "cmd/") { - continue + for _, name := range pkgNames { + // - Package "unsafe" contains special signatures requiring + // extra care when printing them - ignore since it is not + // going to change w/o a language change. + // - We don't care about the API of commands. + if name != "unsafe" && !strings.HasPrefix(name, "cmd/") { + w.export(w.Import(name)) } - if fi, err := os.Stat(filepath.Join(w.root, pkg)); err != nil || !fi.IsDir() { - log.Fatalf("no source in tree for package %q", pkg) - } - w.WalkPackage(pkg) } + ctxName := contextName(context) for _, f := range w.Features() { if featureCtx[f] == nil { @@ -194,7 +184,7 @@ func main() { if *checkFile == "" { sort.Strings(features) for _, f := range features { - fmt.Fprintf(bw, "%s\n", f) + fmt.Fprintln(bw, f) } return } @@ -208,6 +198,22 @@ func main() { fail = !compareAPI(bw, features, required, optional, exception) } +// export emits the exported package features. +func (w *Walker) export(pkg *types.Package) { + if *verbose { + log.Println(pkg) + } + pop := w.pushScope("pkg " + pkg.Path()) + w.current = pkg + scope := pkg.Scope() + for _, name := range scope.Names() { + if ast.IsExported(name) { + w.emitObj(scope.Lookup(name)) + } + } + pop() +} + func set(items []string) map[string]bool { s := make(map[string]bool) for _, v := range items { @@ -304,53 +310,26 @@ func fileFeatures(filename string) []string { return strings.Split(text, "\n") } -// pkgSymbol represents a symbol in a package -type pkgSymbol struct { - pkg string // "net/http" - symbol string // "RoundTripper" -} - var fset = token.NewFileSet() type Walker struct { - context *build.Context - root string - scope []string - features map[string]bool // set - lastConstType string - curPackageName string - curPackage *ast.Package - prevConstType map[pkgSymbol]string - constDep map[string]string // key's const identifier has type of future value const identifier - packageState map[string]loadState - interfaces map[pkgSymbol]*ast.InterfaceType - functionTypes map[pkgSymbol]string // symbol => return type - selectorFullPkg map[string]string // "http" => "net/http", updated by imports - wantedPkg map[string]bool // packages requested on the command line + context *build.Context + root string + scope []string + current *types.Package + features map[string]bool // set + imported map[string]*types.Package // packages already imported } -func NewWalker() *Walker { +func NewWalker(context *build.Context, root string) *Walker { return &Walker{ - features: make(map[string]bool), - packageState: make(map[string]loadState), - interfaces: make(map[pkgSymbol]*ast.InterfaceType), - functionTypes: make(map[pkgSymbol]string), - selectorFullPkg: make(map[string]string), - wantedPkg: make(map[string]bool), - prevConstType: make(map[pkgSymbol]string), - root: filepath.Join(build.Default.GOROOT, "src/pkg"), + context: context, + root: root, + features: map[string]bool{}, + imported: map[string]*types.Package{"unsafe": types.Unsafe}, } } -// loadState is the state of a package's parsing. -type loadState int - -const ( - notLoaded loadState = iota - loading - loaded -) - func (w *Walker) Features() (fs []string) { for f := range w.features { fs = append(fs, f) @@ -359,127 +338,133 @@ func (w *Walker) Features() (fs []string) { return } -// fileDeps returns the imports in a file. -func fileDeps(f *ast.File) (pkgs []string) { - for _, is := range f.Imports { - fpkg, err := strconv.Unquote(is.Path.Value) +var parsedFileCache = make(map[string]*ast.File) + +func (w *Walker) parseFile(dir, file string) (*ast.File, error) { + filename := filepath.Join(dir, file) + f, _ := parsedFileCache[filename] + if f != nil { + return f, nil + } + + var err error + + // generate missing context-dependent files. + + if w.context != nil && file == fmt.Sprintf("zgoos_%s.go", w.context.GOOS) { + src := fmt.Sprintf("package runtime; const theGoos = `%s`", w.context.GOOS) + f, err = parser.ParseFile(fset, filename, src, 0) if err != nil { - log.Fatalf("error unquoting import string %q: %v", is.Path.Value, err) - } - if fpkg != "C" { - pkgs = append(pkgs, fpkg) + log.Fatalf("incorrect generated file: %s", err) } } - return -} -var parsedFileCache = make(map[string]*ast.File) + if w.context != nil && file == fmt.Sprintf("zgoarch_%s.go", w.context.GOARCH) { + src := fmt.Sprintf("package runtime; const theGoarch = `%s`", w.context.GOARCH) + f, err = parser.ParseFile(fset, filename, src, 0) + if err != nil { + log.Fatalf("incorrect generated file: %s", err) + } + } -func parseFile(filename string) (*ast.File, error) { - f, ok := parsedFileCache[filename] - if !ok { - var err error + if f == nil { f, err = parser.ParseFile(fset, filename, nil, 0) if err != nil { return nil, err } - parsedFileCache[filename] = f } - return clone(f).(*ast.File), nil + + parsedFileCache[filename] = f + return f, nil } -// WalkPackage walks all files in package `name'. -// WalkPackage does nothing if the package has already been loaded. -func (w *Walker) WalkPackage(name string) { - switch w.packageState[name] { - case loading: - log.Fatalf("import cycle loading package %q?", name) - case loaded: - return +func contains(list []string, s string) bool { + for _, t := range list { + if t == s { + return true + } } - w.packageState[name] = loading - defer func() { - w.packageState[name] = loaded - }() + return false +} + +// Importing is a sentinel taking the place in Walker.imported +// for a package that is in the process of being imported. +var importing types.Package + +func (w *Walker) Import(name string) (pkg *types.Package) { + pkg = w.imported[name] + if pkg != nil { + if pkg == &importing { + log.Fatalf("cycle importing package %q", name) + } + return pkg + } + w.imported[name] = &importing + + // Determine package files. dir := filepath.Join(w.root, filepath.FromSlash(name)) + if fi, err := os.Stat(dir); err != nil || !fi.IsDir() { + log.Fatalf("no source in tree for package %q", pkg) + } - ctxt := w.context - if ctxt == nil { - ctxt = &build.Default + context := w.context + if context == nil { + context = &build.Default } - info, err := ctxt.ImportDir(dir, 0) + info, err := context.ImportDir(dir, 0) if err != nil { - if strings.Contains(err.Error(), "no Go source files") { + if _, nogo := err.(*build.NoGoError); nogo { return } log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, dir, err) } + filenames := append(append([]string{}, info.GoFiles...), info.CgoFiles...) - apkg := &ast.Package{ - Files: make(map[string]*ast.File), - } - - files := append(append([]string{}, info.GoFiles...), info.CgoFiles...) - for _, file := range files { - f, err := parseFile(filepath.Join(dir, file)) - if err != nil { - log.Fatalf("error parsing package %s, file %s: %v", name, file, err) + // Certain files only exist when building for the specified context. + // Add them manually. + if name == "runtime" { + n := fmt.Sprintf("zgoos_%s.go", w.context.GOOS) + if !contains(filenames, n) { + filenames = append(filenames, n) } - apkg.Files[file] = f - for _, dep := range fileDeps(f) { - w.WalkPackage(dep) + n = fmt.Sprintf("zgoarch_%s.go", w.context.GOARCH) + if !contains(filenames, n) { + filenames = append(filenames, n) } } - if *verbose { - log.Printf("package %s", name) - } - pop := w.pushScope("pkg " + name) - defer pop() - - w.curPackageName = name - w.curPackage = apkg - w.constDep = map[string]string{} - - for _, afile := range apkg.Files { - w.recordTypes(afile) - } - - // Register all function declarations first. - for _, afile := range apkg.Files { - for _, di := range afile.Decls { - if d, ok := di.(*ast.FuncDecl); ok { - w.peekFuncDecl(d) - } + // Parse package files. + var files []*ast.File + for _, file := range filenames { + f, err := w.parseFile(dir, file) + if err != nil { + log.Fatalf("error parsing package %s: %s", name, err) } + files = append(files, f) } - for _, afile := range apkg.Files { - w.walkFile(afile) + // Type-check package files. + conf := types.Config{ + IgnoreFuncBodies: true, + FakeImportC: true, + Import: func(imports map[string]*types.Package, name string) (*types.Package, error) { + pkg := w.Import(name) + imports[name] = pkg + return pkg, nil + }, } - - w.resolveConstantDeps() - - // Now that we're done walking types, vars and consts - // in the *ast.Package, use go/doc to do the rest - // (functions and methods). This is done here because - // go/doc is destructive. We can't use the - // *ast.Package after this. - dpkg := doc.New(apkg, name, doc.AllMethods) - - for _, t := range dpkg.Types { - // Move funcs up to the top-level, not hiding in the Types. - dpkg.Funcs = append(dpkg.Funcs, t.Funcs...) - - for _, m := range t.Methods { - w.walkFuncDecl(m.Decl) + pkg, err = conf.Check(name, fset, files, nil) + if err != nil { + ctxt := "" + if w.context != nil { + ctxt = fmt.Sprintf("%s-%s", w.context.GOOS, w.context.GOARCH) } + log.Fatalf("error typechecking package %s: %s (%s)", name, err, ctxt) } - for _, f := range dpkg.Funcs { - w.walkFuncDecl(f.Decl) - } + w.imported[name] = pkg + return } // pushScope enters a new scope (walking a package, type, node, etc) @@ -498,707 +483,310 @@ func (w *Walker) pushScope(name string) (popFunc func()) { } } -func (w *Walker) recordTypes(file *ast.File) { - for _, di := range file.Decls { - switch d := di.(type) { - case *ast.GenDecl: - switch d.Tok { - case token.TYPE: - for _, sp := range d.Specs { - ts := sp.(*ast.TypeSpec) - name := ts.Name.Name - if ast.IsExported(name) { - if it, ok := ts.Type.(*ast.InterfaceType); ok { - w.noteInterface(name, it) - } - } - } - } +func sortedMethodNames(typ *types.Interface) []string { + n := typ.NumMethods() + list := make([]string, n) + for i := range list { + list[i] = typ.Method(i).Name() + } + sort.Strings(list) + return list +} + +func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { + switch typ := typ.(type) { + case *types.Basic: + s := typ.Name() + switch typ.Kind() { + case types.UnsafePointer: + s = "unsafe.Pointer" + case types.UntypedBool: + s = "ideal-bool" + case types.UntypedInt: + s = "ideal-int" + case types.UntypedRune: + // "ideal-char" for compatibility with old tool + // TODO(gri) change to "ideal-rune" + s = "ideal-char" + case types.UntypedFloat: + s = "ideal-float" + case types.UntypedComplex: + s = "ideal-complex" + case types.UntypedString: + s = "ideal-string" + case types.UntypedNil: + panic("should never see untyped nil type") + default: + switch s { + case "byte": + s = "uint8" + case "rune": + s = "int32" + } + } + buf.WriteString(s) + + case *types.Array: + fmt.Fprintf(buf, "[%d]", typ.Len()) + w.writeType(buf, typ.Elem()) + + case *types.Slice: + buf.WriteString("[]") + w.writeType(buf, typ.Elem()) + + case *types.Struct: + buf.WriteString("struct") + + case *types.Pointer: + buf.WriteByte('*') + w.writeType(buf, typ.Elem()) + + case *types.Tuple: + panic("should never see a tuple type") + + case *types.Signature: + buf.WriteString("func") + w.writeSignature(buf, typ) + + case *types.Interface: + buf.WriteString("interface{") + if typ.NumMethods() > 0 { + buf.WriteByte(' ') + buf.WriteString(strings.Join(sortedMethodNames(typ), ", ")) + buf.WriteByte(' ') + } + buf.WriteString("}") + + case *types.Map: + buf.WriteString("map[") + w.writeType(buf, typ.Key()) + buf.WriteByte(']') + w.writeType(buf, typ.Elem()) + + case *types.Chan: + var s string + switch typ.Dir() { + case ast.SEND: + s = "chan<- " + case ast.RECV: + s = "<-chan " + default: + s = "chan " } - } -} + buf.WriteString(s) + w.writeType(buf, typ.Elem()) -func (w *Walker) walkFile(file *ast.File) { - // Not entering a scope here; file boundaries aren't interesting. - for _, di := range file.Decls { - switch d := di.(type) { - case *ast.GenDecl: - switch d.Tok { - case token.IMPORT: - for _, sp := range d.Specs { - is := sp.(*ast.ImportSpec) - fpath, err := strconv.Unquote(is.Path.Value) - if err != nil { - log.Fatal(err) - } - name := path.Base(fpath) - if is.Name != nil { - name = is.Name.Name - } - w.selectorFullPkg[name] = fpath - } - case token.CONST: - for _, sp := range d.Specs { - w.walkConst(sp.(*ast.ValueSpec)) - } - case token.TYPE: - for _, sp := range d.Specs { - w.walkTypeSpec(sp.(*ast.TypeSpec)) - } - case token.VAR: - for _, sp := range d.Specs { - w.walkVar(sp.(*ast.ValueSpec)) - } - default: - log.Fatalf("unknown token type %d in GenDecl", d.Tok) - } - case *ast.FuncDecl: - // Ignore. Handled in subsequent pass, by go/doc. - default: - log.Printf("unhandled %T, %#v\n", di, di) - printer.Fprint(os.Stderr, fset, di) - os.Stderr.Write([]byte("\n")) + case *types.Named: + obj := typ.Obj() + pkg := obj.Pkg() + if pkg != nil && pkg != w.current { + buf.WriteString(pkg.Name()) + buf.WriteByte('.') } - } -} + buf.WriteString(typ.Obj().Name()) -var constType = map[token.Token]string{ - token.INT: "ideal-int", - token.FLOAT: "ideal-float", - token.STRING: "ideal-string", - token.CHAR: "ideal-char", - token.IMAG: "ideal-imag", + default: + panic(fmt.Sprintf("unknown type %T", typ)) + } } -var varType = map[token.Token]string{ - token.INT: "int", - token.FLOAT: "float64", - token.STRING: "string", - token.CHAR: "rune", - token.IMAG: "complex128", +func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) { + w.writeParams(buf, sig.Params(), sig.IsVariadic()) + switch res := sig.Results(); res.Len() { + case 0: + // nothing to do + case 1: + buf.WriteByte(' ') + w.writeType(buf, res.At(0).Type()) + default: + buf.WriteByte(' ') + w.writeParams(buf, res, false) + } } -var errTODO = errors.New("TODO") - -func (w *Walker) constValueType(vi interface{}) (string, error) { - switch v := vi.(type) { - case *ast.BasicLit: - litType, ok := constType[v.Kind] - if !ok { - return "", fmt.Errorf("unknown basic literal kind %#v", v) - } - return litType, nil - case *ast.UnaryExpr: - return w.constValueType(v.X) - case *ast.SelectorExpr: - lhs := w.nodeString(v.X) - rhs := w.nodeString(v.Sel) - pkg, ok := w.selectorFullPkg[lhs] - if !ok { - return "", fmt.Errorf("unknown constant reference; unknown package in expression %s.%s", lhs, rhs) - } - if t, ok := w.prevConstType[pkgSymbol{pkg, rhs}]; ok { - return t, nil - } - return "", fmt.Errorf("unknown constant reference to %s.%s", lhs, rhs) - case *ast.Ident: - if v.Name == "iota" { - return "ideal-int", nil // hack. - } - if v.Name == "false" || v.Name == "true" { - return "bool", nil - } - if v.Name == "intSize" && w.curPackageName == "strconv" { - // Hack. - return "ideal-int", nil - } - if t, ok := w.prevConstType[pkgSymbol{w.curPackageName, v.Name}]; ok { - return t, nil - } - return constDepPrefix + v.Name, nil - case *ast.BinaryExpr: - switch v.Op { - case token.EQL, token.LSS, token.GTR, token.NOT, token.NEQ, token.LEQ, token.GEQ: - return "bool", nil - } - left, err := w.constValueType(v.X) - if err != nil { - return "", err +func (w *Walker) writeParams(buf *bytes.Buffer, t *types.Tuple, variadic bool) { + buf.WriteByte('(') + for i, n := 0, t.Len(); i < n; i++ { + if i > 0 { + buf.WriteString(", ") } - right, err := w.constValueType(v.Y) - if err != nil { - return "", err + typ := t.At(i).Type() + if variadic && i+1 == n { + buf.WriteString("...") + typ = typ.(*types.Slice).Elem() } - if left != right { - // TODO(bradfitz): encode the real rules here, - // rather than this mess. - if left == "ideal-int" && right == "ideal-float" { - return "ideal-float", nil // math.Log2E - } - if left == "ideal-char" && right == "ideal-int" { - return "ideal-int", nil // math/big.MaxBase - } - if left == "ideal-int" && right == "ideal-char" { - return "ideal-int", nil // text/scanner.GoWhitespace - } - if left == "ideal-int" && right == "Duration" { - // Hack, for package time. - return "Duration", nil - } - if left == "ideal-int" && !strings.HasPrefix(right, "ideal-") { - return right, nil - } - if right == "ideal-int" && !strings.HasPrefix(left, "ideal-") { - return left, nil - } - if strings.HasPrefix(left, constDepPrefix) && strings.HasPrefix(right, constDepPrefix) { - // Just pick one. - // e.g. text/scanner GoTokens const-dependency:ScanIdents, const-dependency:ScanFloats - return left, nil - } - return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right) - } - return left, nil - case *ast.CallExpr: - // Not a call, but a type conversion. - return w.nodeString(v.Fun), nil - case *ast.ParenExpr: - return w.constValueType(v.X) + w.writeType(buf, typ) } - return "", fmt.Errorf("unknown const value type %T", vi) + buf.WriteByte(')') } -func (w *Walker) varValueType(vi interface{}) (string, error) { - switch v := vi.(type) { - case *ast.BasicLit: - litType, ok := varType[v.Kind] - if !ok { - return "", fmt.Errorf("unknown basic literal kind %#v", v) - } - return litType, nil - case *ast.CompositeLit: - return w.nodeString(v.Type), nil - case *ast.FuncLit: - return w.nodeString(w.namelessType(v.Type)), nil - case *ast.UnaryExpr: - if v.Op == token.AND { - typ, err := w.varValueType(v.X) - return "*" + typ, err - } - return "", fmt.Errorf("unknown unary expr: %#v", v) - case *ast.SelectorExpr: - return "", errTODO - case *ast.Ident: - node, _, ok := w.resolveName(v.Name) - if !ok { - return "", fmt.Errorf("unresolved identifier: %q", v.Name) - } - return w.varValueType(node) - case *ast.BinaryExpr: - left, err := w.varValueType(v.X) - if err != nil { - return "", err - } - right, err := w.varValueType(v.Y) - if err != nil { - return "", err - } - if left != right { - return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right) - } - return left, nil - case *ast.ParenExpr: - return w.varValueType(v.X) - case *ast.CallExpr: - var funSym pkgSymbol - if selnode, ok := v.Fun.(*ast.SelectorExpr); ok { - // assume it is not a method. - pkg, ok := w.selectorFullPkg[w.nodeString(selnode.X)] - if !ok { - return "", fmt.Errorf("not a package: %s", w.nodeString(selnode.X)) - } - funSym = pkgSymbol{pkg, selnode.Sel.Name} - if retType, ok := w.functionTypes[funSym]; ok { - if ast.IsExported(retType) && pkg != w.curPackageName { - // otherpkg.F returning an exported type from otherpkg. - return pkg + "." + retType, nil - } else { - return retType, nil - } - } - } else { - funSym = pkgSymbol{w.curPackageName, w.nodeString(v.Fun)} - if retType, ok := w.functionTypes[funSym]; ok { - return retType, nil - } - } - // maybe a function call; maybe a conversion. Need to lookup type. - // TODO(bradfitz): this is a hack, but arguably most of this tool is, - // until the Go AST has type information. - nodeStr := w.nodeString(v.Fun) - switch nodeStr { - case "string", "[]byte": - return nodeStr, nil - } - return "", fmt.Errorf("not a known function %q", nodeStr) - default: - return "", fmt.Errorf("unknown const value type %T", vi) - } +func (w *Walker) typeString(typ types.Type) string { + var buf bytes.Buffer + w.writeType(&buf, typ) + return buf.String() } -// resolveName finds a top-level node named name and returns the node -// v and its type t, if known. -func (w *Walker) resolveName(name string) (v interface{}, t interface{}, ok bool) { - for _, file := range w.curPackage.Files { - for _, di := range file.Decls { - switch d := di.(type) { - case *ast.GenDecl: - switch d.Tok { - case token.VAR: - for _, sp := range d.Specs { - vs := sp.(*ast.ValueSpec) - for i, vname := range vs.Names { - if vname.Name == name { - if len(vs.Values) > i { - return vs.Values[i], vs.Type, true - } - return nil, vs.Type, true - } - } - } - } - } - } - } - return nil, nil, false +func (w *Walker) signatureString(sig *types.Signature) string { + var buf bytes.Buffer + w.writeSignature(&buf, sig) + return buf.String() } -// constDepPrefix is a magic prefix that is used by constValueType -// and walkConst to signal that a type isn't known yet. These are -// resolved at the end of walking of a package's files. -const constDepPrefix = "const-dependency:" +func (w *Walker) emitObj(obj types.Object) { + switch obj := obj.(type) { + case *types.Const: + w.emitf("const %s %s", obj.Name(), w.typeString(obj.Type())) -func (w *Walker) walkConst(vs *ast.ValueSpec) { - for _, ident := range vs.Names { - litType := "" - if vs.Type != nil { - litType = w.nodeString(vs.Type) - } else { - litType = w.lastConstType - if vs.Values != nil { - if len(vs.Values) != 1 { - log.Fatalf("const %q, values: %#v", ident.Name, vs.Values) - } - var err error - litType, err = w.constValueType(vs.Values[0]) - if err != nil { - log.Fatalf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err) - } - } - } - if dep := strings.TrimPrefix(litType, constDepPrefix); dep != litType { - w.constDep[ident.Name] = dep - continue - } - if litType == "" { - log.Fatalf("unknown kind in const %q", ident.Name) - } - w.lastConstType = litType + case *types.Var: + w.emitf("var %s %s", obj.Name(), w.typeString(obj.Type())) - w.prevConstType[pkgSymbol{w.curPackageName, ident.Name}] = litType + case *types.TypeName: + w.emitType(obj) - if ast.IsExported(ident.Name) { - w.emitFeature(fmt.Sprintf("const %s %s", ident, litType)) - } - } -} + case *types.Func: + w.emitFunc(obj) -func (w *Walker) resolveConstantDeps() { - var findConstType func(string) string - findConstType = func(ident string) string { - if dep, ok := w.constDep[ident]; ok { - return findConstType(dep) - } - if t, ok := w.prevConstType[pkgSymbol{w.curPackageName, ident}]; ok { - return t - } - return "" - } - for ident := range w.constDep { - if !ast.IsExported(ident) { - continue - } - t := findConstType(ident) - if t == "" { - log.Fatalf("failed to resolve constant %q", ident) - } - w.emitFeature(fmt.Sprintf("const %s %s", ident, t)) + default: + panic("unknown object: " + obj.String()) } } -func (w *Walker) walkVar(vs *ast.ValueSpec) { - for i, ident := range vs.Names { - if !ast.IsExported(ident.Name) { - continue - } +func (w *Walker) emitType(obj *types.TypeName) { + name := obj.Name() + typ := obj.Type() + switch typ := typ.Underlying().(type) { + case *types.Struct: + w.emitStructType(name, typ) + case *types.Interface: + w.emitIfaceType(name, typ) + return // methods are handled by emitIfaceType + default: + w.emitf("type %s %s", name, w.typeString(typ.Underlying())) + } - typ := "" - if vs.Type != nil { - typ = w.nodeString(vs.Type) - } else { - if len(vs.Values) == 0 { - log.Fatalf("no values for var %q", ident.Name) - } - if len(vs.Values) > 1 { - log.Fatalf("more than 1 values in ValueSpec not handled, var %q", ident.Name) - } - var err error - typ, err = w.varValueType(vs.Values[i]) - if err != nil { - log.Fatalf("unknown type of variable %q, type %T, error = %v\ncode: %s", - ident.Name, vs.Values[i], err, w.nodeString(vs.Values[i])) + // emit methods with value receiver + var methodNames map[string]bool + vset := typ.MethodSet() + for i, n := 0, vset.Len(); i < n; i++ { + m := vset.At(i) + if m.Obj().IsExported() { + w.emitMethod(m) + if methodNames == nil { + methodNames = make(map[string]bool) } + methodNames[m.Obj().Name()] = true } - w.emitFeature(fmt.Sprintf("var %s %s", ident, typ)) - } -} - -func (w *Walker) nodeString(node interface{}) string { - if node == nil { - return "" - } - var b bytes.Buffer - printer.Fprint(&b, fset, node) - return b.String() -} - -func (w *Walker) nodeDebug(node interface{}) string { - if node == nil { - return "" } - var b bytes.Buffer - ast.Fprint(&b, fset, node, nil) - return b.String() -} - -func (w *Walker) noteInterface(name string, it *ast.InterfaceType) { - w.interfaces[pkgSymbol{w.curPackageName, name}] = it -} -func (w *Walker) walkTypeSpec(ts *ast.TypeSpec) { - name := ts.Name.Name - if !ast.IsExported(name) { - return - } - switch t := ts.Type.(type) { - case *ast.StructType: - w.walkStructType(name, t) - case *ast.InterfaceType: - w.walkInterfaceType(name, t) - default: - w.emitFeature(fmt.Sprintf("type %s %s", name, w.nodeString(w.namelessType(ts.Type)))) + // emit methods with pointer receiver; exclude + // methods that we have emitted already + // (the method set of *T includes the methods of T) + pset := types.NewPointer(typ).MethodSet() + for i, n := 0, pset.Len(); i < n; i++ { + m := pset.At(i) + if m.Obj().IsExported() && !methodNames[m.Obj().Name()] { + w.emitMethod(m) + } } } -func (w *Walker) walkStructType(name string, t *ast.StructType) { +func (w *Walker) emitStructType(name string, typ *types.Struct) { typeStruct := fmt.Sprintf("type %s struct", name) - w.emitFeature(typeStruct) - pop := w.pushScope(typeStruct) - defer pop() - for _, f := range t.Fields.List { - typ := f.Type - for _, name := range f.Names { - if ast.IsExported(name.Name) { - w.emitFeature(fmt.Sprintf("%s %s", name, w.nodeString(w.namelessType(typ)))) - } + w.emitf(typeStruct) + defer w.pushScope(typeStruct)() + + for i := 0; i < typ.NumFields(); i++ { + f := typ.Field(i) + if !f.IsExported() { + continue } - if f.Names == nil { - switch v := typ.(type) { - case *ast.Ident: - if ast.IsExported(v.Name) { - w.emitFeature(fmt.Sprintf("embedded %s", v.Name)) - } - case *ast.StarExpr: - switch vv := v.X.(type) { - case *ast.Ident: - if ast.IsExported(vv.Name) { - w.emitFeature(fmt.Sprintf("embedded *%s", vv.Name)) - } - case *ast.SelectorExpr: - w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ))) - default: - log.Fatalf("unable to handle embedded starexpr before %T", typ) - } - case *ast.SelectorExpr: - w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ))) - default: - log.Fatalf("unable to handle embedded %T", typ) - } + typ := f.Type() + if f.Anonymous() { + w.emitf("embedded %s", w.typeString(typ)) + continue } + w.emitf("%s %s", f.Name(), w.typeString(typ)) } } -// method is a method of an interface. -type method struct { - name string // "Read" - sig string // "([]byte) (int, error)", from funcSigString -} - -// interfaceMethods returns the expanded list of exported methods for an interface. -// The boolean complete reports whether the list contains all methods (that is, the -// interface has no unexported methods). -// pkg is the complete package name ("net/http") -// iname is the interface name. -func (w *Walker) interfaceMethods(pkg, iname string) (methods []method, complete bool) { - t, ok := w.interfaces[pkgSymbol{pkg, iname}] - if !ok { - log.Fatalf("failed to find interface %s.%s", pkg, iname) - } +func (w *Walker) emitIfaceType(name string, typ *types.Interface) { + pop := w.pushScope("type " + name + " interface") - complete = true - for _, f := range t.Methods.List { - typ := f.Type - switch tv := typ.(type) { - case *ast.FuncType: - for _, mname := range f.Names { - if ast.IsExported(mname.Name) { - ft := typ.(*ast.FuncType) - methods = append(methods, method{ - name: mname.Name, - sig: w.funcSigString(ft), - }) - } else { - complete = false - } - } - case *ast.Ident: - embedded := typ.(*ast.Ident).Name - if embedded == "error" { - methods = append(methods, method{ - name: "Error", - sig: "() string", - }) - continue - } - if !ast.IsExported(embedded) { - log.Fatalf("unexported embedded interface %q in exported interface %s.%s; confused", - embedded, pkg, iname) - } - m, c := w.interfaceMethods(pkg, embedded) - methods = append(methods, m...) - complete = complete && c - case *ast.SelectorExpr: - lhs := w.nodeString(tv.X) - rhs := w.nodeString(tv.Sel) - fpkg, ok := w.selectorFullPkg[lhs] - if !ok { - log.Fatalf("can't resolve selector %q in interface %s.%s", lhs, pkg, iname) - } - m, c := w.interfaceMethods(fpkg, rhs) - methods = append(methods, m...) - complete = complete && c - default: - log.Fatalf("unknown type %T in interface field", typ) + var methodNames []string + complete := true + mset := typ.MethodSet() + for i, n := 0, mset.Len(); i < n; i++ { + m := mset.At(i).Obj().(*types.Func) + if !m.IsExported() { + complete = false + continue } + methodNames = append(methodNames, m.Name()) + w.emitf("%s%s", m.Name(), w.signatureString(m.Type().(*types.Signature))) } - return -} -func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) { - methNames := []string{} - pop := w.pushScope("type " + name + " interface") - methods, complete := w.interfaceMethods(w.curPackageName, name) - for _, m := range methods { - methNames = append(methNames, m.name) - w.emitFeature(fmt.Sprintf("%s%s", m.name, m.sig)) - } if !complete { // The method set has unexported methods, so all the // implementations are provided by the same package, // so the method set can be extended. Instead of recording // the full set of names (below), record only that there were // unexported methods. (If the interface shrinks, we will notice - // because a method signature emitted during the last loop, + // because a method signature emitted during the last loop // will disappear.) - w.emitFeature("unexported methods") + w.emitf("unexported methods") } + pop() if !complete { return } - sort.Strings(methNames) - if len(methNames) == 0 { - w.emitFeature(fmt.Sprintf("type %s interface {}", name)) - } else { - w.emitFeature(fmt.Sprintf("type %s interface { %s }", name, strings.Join(methNames, ", "))) - } -} - -func (w *Walker) peekFuncDecl(f *ast.FuncDecl) { - if f.Recv != nil { + if len(methodNames) == 0 { + w.emitf("type %s interface {}", name) return } - // Record return type for later use. - if f.Type.Results != nil && len(f.Type.Results.List) == 1 { - retType := w.nodeString(w.namelessType(f.Type.Results.List[0].Type)) - w.functionTypes[pkgSymbol{w.curPackageName, f.Name.Name}] = retType - } -} - -func (w *Walker) walkFuncDecl(f *ast.FuncDecl) { - if !ast.IsExported(f.Name.Name) { - return - } - if f.Recv != nil { - // Method. - recvType := w.nodeString(f.Recv.List[0].Type) - keep := ast.IsExported(recvType) || - (strings.HasPrefix(recvType, "*") && - ast.IsExported(recvType[1:])) - if !keep { - return - } - w.emitFeature(fmt.Sprintf("method (%s) %s%s", recvType, f.Name.Name, w.funcSigString(f.Type))) - return - } - // Else, a function - w.emitFeature(fmt.Sprintf("func %s%s", f.Name.Name, w.funcSigString(f.Type))) -} -func (w *Walker) funcSigString(ft *ast.FuncType) string { - var b bytes.Buffer - writeField := func(b *bytes.Buffer, f *ast.Field) { - if n := len(f.Names); n > 1 { - for i := 0; i < n; i++ { - if i > 0 { - b.WriteString(", ") - } - b.WriteString(w.nodeString(w.namelessType(f.Type))) - } - } else { - b.WriteString(w.nodeString(w.namelessType(f.Type))) - } - } - b.WriteByte('(') - if ft.Params != nil { - for i, f := range ft.Params.List { - if i > 0 { - b.WriteString(", ") - } - writeField(&b, f) - } - } - b.WriteByte(')') - if ft.Results != nil { - nr := 0 - for _, f := range ft.Results.List { - if n := len(f.Names); n > 1 { - nr += n - } else { - nr++ - } - } - if nr > 0 { - b.WriteByte(' ') - if nr > 1 { - b.WriteByte('(') - } - for i, f := range ft.Results.List { - if i > 0 { - b.WriteString(", ") - } - writeField(&b, f) - } - if nr > 1 { - b.WriteByte(')') - } - } - } - return b.String() + sort.Strings(methodNames) + w.emitf("type %s interface { %s }", name, strings.Join(methodNames, ", ")) } -// namelessType returns a type node that lacks any variable names. -func (w *Walker) namelessType(t interface{}) interface{} { - ft, ok := t.(*ast.FuncType) - if !ok { - return t - } - return &ast.FuncType{ - Params: w.namelessFieldList(ft.Params), - Results: w.namelessFieldList(ft.Results), +func (w *Walker) emitFunc(f *types.Func) { + sig := f.Type().(*types.Signature) + if sig.Recv() != nil { + panic("method considered a regular function: " + f.String()) } + w.emitf("func %s%s", f.Name(), w.signatureString(sig)) } -// namelessFieldList returns a deep clone of fl, with the cloned fields -// lacking names. -func (w *Walker) namelessFieldList(fl *ast.FieldList) *ast.FieldList { - fl2 := &ast.FieldList{} - if fl != nil { - for _, f := range fl.List { - repeats := 1 - if len(f.Names) > 1 { - repeats = len(f.Names) - } - for i := 0; i < repeats; i++ { - fl2.List = append(fl2.List, w.namelessField(f)) - } +func (w *Walker) emitMethod(m *types.Selection) { + sig := m.Type().(*types.Signature) + recv := sig.Recv().Type() + // report exported methods with unexported reveiver base type + if true { + base := recv + if p, _ := recv.(*types.Pointer); p != nil { + base = p.Elem() + } + if obj := base.(*types.Named).Obj(); !obj.IsExported() { + log.Fatalf("exported method with unexported receiver base type: %s", m) } } - return fl2 + w.emitf("method (%s) %s%s", w.typeString(recv), m.Obj().Name(), w.signatureString(sig)) } -// namelessField clones f, but not preserving the names of fields. -// (comments and tags are also ignored) -func (w *Walker) namelessField(f *ast.Field) *ast.Field { - return &ast.Field{ - Type: f.Type, +func (w *Walker) emitf(format string, args ...interface{}) { + f := strings.Join(w.scope, ", ") + ", " + fmt.Sprintf(format, args...) + if strings.Contains(f, "\n") { + panic("feature contains newlines: " + f) } -} - -var ( - byteRx = regexp.MustCompile(`\bbyte\b`) - runeRx = regexp.MustCompile(`\brune\b`) -) -func (w *Walker) emitFeature(feature string) { - if !w.wantedPkg[w.curPackageName] { - return - } - if strings.Contains(feature, "byte") { - feature = byteRx.ReplaceAllString(feature, "uint8") - } - if strings.Contains(feature, "rune") { - feature = runeRx.ReplaceAllString(feature, "int32") - } - f := strings.Join(w.scope, ", ") + ", " + feature if _, dup := w.features[f]; dup { panic("duplicate feature inserted: " + f) } - - if strings.Contains(f, "\n") { - // TODO: for now, just skip over the - // runtime.MemStatsType.BySize type, which this tool - // doesn't properly handle. It's pretty low-level, - // though, so not super important to protect against. - if strings.HasPrefix(f, "pkg runtime") && strings.Contains(f, "BySize [61]struct") { - return - } - panic("feature contains newlines: " + f) - } - w.features[f] = true + if *verbose { log.Printf("feature: %s", f) } } - -func strListContains(l []string, s string) bool { - for _, v := range l { - if v == s { - return true - } - } - return false -} diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go index 226748ac4a..a1e762bafc 100644 --- a/src/cmd/api/goapi_test.go +++ b/src/cmd/api/goapi_test.go @@ -1,3 +1,5 @@ +// +build api_tool + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -33,12 +35,10 @@ func TestGolden(t *testing.T) { if !fi.IsDir() { continue } - w := NewWalker() - w.wantedPkg[fi.Name()] = true - w.root = "testdata/src/pkg" goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt") - w.WalkPackage(fi.Name()) + w := NewWalker(nil, "testdata/src/pkg") + w.export(w.Import(fi.Name())) if *updateGolden { os.Remove(goldenFile) diff --git a/src/cmd/api/testdata/src/pkg/p1/golden.txt b/src/cmd/api/testdata/src/pkg/p1/golden.txt index abcc0ce6c4..12fd452ffe 100644 --- a/src/cmd/api/testdata/src/pkg/p1/golden.txt +++ b/src/cmd/api/testdata/src/pkg/p1/golden.txt @@ -1,7 +1,7 @@ pkg p1, const A ideal-int pkg p1, const A64 int64 pkg p1, const AIsLowerA ideal-int -pkg p1, const B ideal-int +pkg p1, const B0 ideal-int pkg p1, const ConstChase2 ideal-int pkg p1, const ConversionConst MyInt pkg p1, const FloatConst ideal-float @@ -10,6 +10,7 @@ pkg p1, func Bar(int8, int16, int64) pkg p1, func Bar1(int8, int16, int64) uint64 pkg p1, func Bar2(int8, int16, int64) (uint8, uint64) pkg p1, func BarE() Error +pkg p1, func Now() Time pkg p1, func PlainFunc(int, int, string) (*B, error) pkg p1, func TakesFunc(func(int) int) pkg p1, method (*B) JustOnB() @@ -34,9 +35,9 @@ pkg p1, type ByteStruct struct, R int32 pkg p1, type Codec struct pkg p1, type Codec struct, Func func(int, int) int pkg p1, type EmbedSelector struct -pkg p1, type EmbedSelector struct, embedded time.Time +pkg p1, type EmbedSelector struct, embedded Time pkg p1, type EmbedURLPtr struct -pkg p1, type EmbedURLPtr struct, embedded *url.URL +pkg p1, type EmbedURLPtr struct, embedded *URL pkg p1, type Embedded struct pkg p1, type Error interface { Error, Temporary } pkg p1, type Error interface, Error() string @@ -58,7 +59,7 @@ pkg p1, type Public interface, X() pkg p1, type Public interface, Y() pkg p1, type S struct pkg p1, type S struct, Public *int -pkg p1, type S struct, PublicTime time.Time +pkg p1, type S struct, PublicTime Time pkg p1, type S2 struct pkg p1, type S2 struct, Extra bool pkg p1, type S2 struct, embedded S @@ -68,6 +69,8 @@ pkg p1, type T struct pkg p1, type TPtrExported struct pkg p1, type TPtrExported struct, embedded *Embedded pkg p1, type TPtrUnexported struct +pkg p1, type Time struct +pkg p1, type URL struct pkg p1, var Byte uint8 pkg p1, var ByteConv []uint8 pkg p1, var ByteFunc func(uint8) int32 @@ -81,5 +84,5 @@ pkg p1, var V1 uint64 pkg p1, var V2 p2.Twoer pkg p1, var VError Error pkg p1, var X I -pkg p1, var X int64 +pkg p1, var X0 int64 pkg p1, var Y int diff --git a/src/cmd/api/testdata/src/pkg/p1/p1.go b/src/cmd/api/testdata/src/pkg/p1/p1.go index f94c9ceeb1..65181b248a 100644 --- a/src/cmd/api/testdata/src/pkg/p1/p1.go +++ b/src/cmd/api/testdata/src/pkg/p1/p1.go @@ -35,7 +35,7 @@ var ( var ChecksumError = ptwo.NewError("gzip checksum error") -const B = 2 +const B0 = 2 const StrConst = "foo" const FloatConst = 1.5 @@ -43,14 +43,18 @@ type myInt int type MyInt int +type Time struct{} + type S struct { Public *int private *int - PublicTime time.Time + PublicTime Time } +type URL struct{} + type EmbedURLPtr struct { - *url.URL + *URL } type S2 struct { @@ -58,7 +62,7 @@ type S2 struct { Extra bool } -var X int64 +var X0 int64 var ( Y int @@ -163,7 +167,7 @@ func (*common) OnBothTandBPtr() {} func (common) OnBothTandBVal() {} type EmbedSelector struct { - time.Time + Time } const ( @@ -174,10 +178,15 @@ const ( func ellipsis(...string) {} +func Now() Time { + var now Time + return now +} + var x = &S{ Public: nil, private: nil, - publicTime: time.Now(), + PublicTime: Now(), } var parenExpr = (1 + 5) -- 2.48.1