whatcanGOwrong
This commit is contained in:
+194
@@ -0,0 +1,194 @@
|
||||
// Copyright 2014 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 analysis performs type and pointer analysis
|
||||
// and generates mark-up for the Go source view.
|
||||
//
|
||||
// The Run method populates a Result object by running type and
|
||||
// (optionally) pointer analysis. The Result object is thread-safe
|
||||
// and at all times may be accessed by a serving thread, even as it is
|
||||
// progressively populated as analysis facts are derived.
|
||||
//
|
||||
// The Result is a mapping from each godoc file URL
|
||||
// (e.g. /src/fmt/print.go) to information about that file. The
|
||||
// information is a list of HTML markup links and a JSON array of
|
||||
// structured data values. Some of the links call client-side
|
||||
// JavaScript functions that index this array.
|
||||
//
|
||||
// The analysis computes mark-up for the following relations:
|
||||
//
|
||||
// IMPORTS: for each ast.ImportSpec, the package that it denotes.
|
||||
//
|
||||
// RESOLUTION: for each ast.Ident, its kind and type, and the location
|
||||
// of its definition.
|
||||
//
|
||||
// METHOD SETS, IMPLEMENTS: for each ast.Ident defining a named type,
|
||||
// its method-set, the set of interfaces it implements or is
|
||||
// implemented by, and its size/align values.
|
||||
//
|
||||
// CALLERS, CALLEES: for each function declaration ('func' token), its
|
||||
// callers, and for each call-site ('(' token), its callees.
|
||||
//
|
||||
// CALLGRAPH: the package docs include an interactive viewer for the
|
||||
// intra-package call graph of "fmt".
|
||||
//
|
||||
// CHANNEL PEERS: for each channel operation make/<-/close, the set of
|
||||
// other channel ops that alias the same channel(s).
|
||||
//
|
||||
// ERRORS: for each locus of a frontend (scanner/parser/type) error, the
|
||||
// location is highlighted in red and hover text provides the compiler
|
||||
// error message.
|
||||
package analysis // import "golang.org/x/tools/godoc/analysis"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// -- links ------------------------------------------------------------
|
||||
|
||||
// A Link is an HTML decoration of the bytes [Start, End) of a file.
|
||||
// Write is called before/after those bytes to emit the mark-up.
|
||||
type Link interface {
|
||||
Start() int
|
||||
End() int
|
||||
Write(w io.Writer, _ int, start bool) // the godoc.LinkWriter signature
|
||||
}
|
||||
|
||||
// -- fileInfo ---------------------------------------------------------
|
||||
|
||||
// FileInfo holds analysis information for the source file view.
|
||||
// Clients must not mutate it.
|
||||
type FileInfo struct {
|
||||
Data []interface{} // JSON serializable values
|
||||
Links []Link // HTML link markup
|
||||
}
|
||||
|
||||
// A fileInfo is the server's store of hyperlinks and JSON data for a
|
||||
// particular file.
|
||||
type fileInfo struct {
|
||||
mu sync.Mutex
|
||||
data []interface{} // JSON objects
|
||||
links []Link
|
||||
sorted bool
|
||||
hasErrors bool // TODO(adonovan): surface this in the UI
|
||||
}
|
||||
|
||||
// get returns the file info in external form.
|
||||
// Callers must not mutate its fields.
|
||||
func (fi *fileInfo) get() FileInfo {
|
||||
var r FileInfo
|
||||
// Copy slices, to avoid races.
|
||||
fi.mu.Lock()
|
||||
r.Data = append(r.Data, fi.data...)
|
||||
if !fi.sorted {
|
||||
sort.Sort(linksByStart(fi.links))
|
||||
fi.sorted = true
|
||||
}
|
||||
r.Links = append(r.Links, fi.links...)
|
||||
fi.mu.Unlock()
|
||||
return r
|
||||
}
|
||||
|
||||
// PackageInfo holds analysis information for the package view.
|
||||
// Clients must not mutate it.
|
||||
type PackageInfo struct {
|
||||
CallGraph []*PCGNodeJSON
|
||||
CallGraphIndex map[string]int
|
||||
Types []*TypeInfoJSON
|
||||
}
|
||||
|
||||
type pkgInfo struct {
|
||||
mu sync.Mutex
|
||||
callGraph []*PCGNodeJSON
|
||||
callGraphIndex map[string]int // keys are (*ssa.Function).RelString()
|
||||
types []*TypeInfoJSON // type info for exported types
|
||||
}
|
||||
|
||||
// get returns the package info in external form.
|
||||
// Callers must not mutate its fields.
|
||||
func (pi *pkgInfo) get() PackageInfo {
|
||||
var r PackageInfo
|
||||
// Copy slices, to avoid races.
|
||||
pi.mu.Lock()
|
||||
r.CallGraph = append(r.CallGraph, pi.callGraph...)
|
||||
r.CallGraphIndex = pi.callGraphIndex
|
||||
r.Types = append(r.Types, pi.types...)
|
||||
pi.mu.Unlock()
|
||||
return r
|
||||
}
|
||||
|
||||
// -- Result -----------------------------------------------------------
|
||||
|
||||
// Result contains the results of analysis.
|
||||
// The result contains a mapping from filenames to a set of HTML links
|
||||
// and JavaScript data referenced by the links.
|
||||
type Result struct {
|
||||
mu sync.Mutex // guards maps (but not their contents)
|
||||
status string // global analysis status
|
||||
fileInfos map[string]*fileInfo // keys are godoc file URLs
|
||||
pkgInfos map[string]*pkgInfo // keys are import paths
|
||||
}
|
||||
|
||||
// fileInfo returns the fileInfo for the specified godoc file URL,
|
||||
// constructing it as needed. Thread-safe.
|
||||
func (res *Result) fileInfo(url string) *fileInfo {
|
||||
res.mu.Lock()
|
||||
fi, ok := res.fileInfos[url]
|
||||
if !ok {
|
||||
if res.fileInfos == nil {
|
||||
res.fileInfos = make(map[string]*fileInfo)
|
||||
}
|
||||
fi = new(fileInfo)
|
||||
res.fileInfos[url] = fi
|
||||
}
|
||||
res.mu.Unlock()
|
||||
return fi
|
||||
}
|
||||
|
||||
// Status returns a human-readable description of the current analysis status.
|
||||
func (res *Result) Status() string {
|
||||
res.mu.Lock()
|
||||
defer res.mu.Unlock()
|
||||
return res.status
|
||||
}
|
||||
|
||||
// FileInfo returns new slices containing opaque JSON values and the
|
||||
// HTML link markup for the specified godoc file URL. Thread-safe.
|
||||
// Callers must not mutate the elements.
|
||||
// It returns "zero" if no data is available.
|
||||
func (res *Result) FileInfo(url string) (fi FileInfo) {
|
||||
return res.fileInfo(url).get()
|
||||
}
|
||||
|
||||
// pkgInfo returns the pkgInfo for the specified import path,
|
||||
// constructing it as needed. Thread-safe.
|
||||
func (res *Result) pkgInfo(importPath string) *pkgInfo {
|
||||
res.mu.Lock()
|
||||
pi, ok := res.pkgInfos[importPath]
|
||||
if !ok {
|
||||
if res.pkgInfos == nil {
|
||||
res.pkgInfos = make(map[string]*pkgInfo)
|
||||
}
|
||||
pi = new(pkgInfo)
|
||||
res.pkgInfos[importPath] = pi
|
||||
}
|
||||
res.mu.Unlock()
|
||||
return pi
|
||||
}
|
||||
|
||||
// PackageInfo returns new slices of JSON values for the callgraph and
|
||||
// type info for the specified package. Thread-safe.
|
||||
// Callers must not mutate its fields.
|
||||
// PackageInfo returns "zero" if no data is available.
|
||||
func (res *Result) PackageInfo(importPath string) PackageInfo {
|
||||
return res.pkgInfo(importPath).get()
|
||||
}
|
||||
|
||||
type linksByStart []Link
|
||||
|
||||
func (a linksByStart) Less(i, j int) bool { return a[i].Start() < a[j].Start() }
|
||||
func (a linksByStart) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a linksByStart) Len() int { return len(a) }
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// Copyright 2014 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 analysis
|
||||
|
||||
// This file defines types used by client-side JavaScript.
|
||||
|
||||
type anchorJSON struct {
|
||||
Text string // HTML
|
||||
Href string // URL
|
||||
}
|
||||
|
||||
// Indicates one of these forms of fact about a type T:
|
||||
// T "is implemented by <ByKind> type <Other>" (ByKind != "", e.g. "array")
|
||||
// T "implements <Other>" (ByKind == "")
|
||||
type implFactJSON struct {
|
||||
ByKind string `json:",omitempty"`
|
||||
Other anchorJSON
|
||||
}
|
||||
|
||||
// Implements facts are grouped by form, for ease of reading.
|
||||
type implGroupJSON struct {
|
||||
Descr string
|
||||
Facts []implFactJSON
|
||||
}
|
||||
|
||||
// JavaScript's onClickIdent() expects a TypeInfoJSON.
|
||||
type TypeInfoJSON struct {
|
||||
Name string // type name
|
||||
Size, Align int64
|
||||
Methods []anchorJSON
|
||||
ImplGroups []implGroupJSON
|
||||
}
|
||||
|
||||
// JavaScript's cgAddChild requires a global array of PCGNodeJSON
|
||||
// called CALLGRAPH, representing the intra-package call graph.
|
||||
// The first element is special and represents "all external callers".
|
||||
type PCGNodeJSON struct {
|
||||
Func anchorJSON
|
||||
Callees []int // indices within CALLGRAPH of nodes called by this one
|
||||
}
|
||||
Reference in New Issue
Block a user