Skip to content

Commit

Permalink
Go indexer: Handle resolution of the 'unsafe' metapackage.
Browse files Browse the repository at this point in the history
Summary:
The type checker does not include "unsafe" as a package dependency, since it
isn't a real package but a special hook for the compiler. For indexing purposes
we pretend it IS s real package so that references will resolve.

- Extractor: Don't treat 'unsafe' as a missing package.
- Add a unit test for resolution of the 'unsafe' package.
- Add ForStandardLibrary to the govname package.

Reviewers: #core_team, shahms

Reviewed By: #core_team, shahms

Differential Revision: https://phabricator-dot-kythe-repo.appspot.com/D1256
  • Loading branch information
M. J. Fromberger committed Jan 12, 2017
1 parent 7e92157 commit 0570c4e
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 3 deletions.
7 changes: 4 additions & 3 deletions kythe/go/extractors/golang/golang.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,11 @@ func (*Package) addFlag(cu *apb.CompilationUnit, name string, values ...string)
func (p *Package) addDeps(cu *apb.CompilationUnit, importPaths []string) []string {
var missing []string
for _, ip := range importPaths {
dep, err := p.ext.addPackage(ip)
if err != nil {
if ip == "unsafe" {
// package unsafe is intrinsic; nothing to do
} else if dep, err := p.ext.addPackage(ip); err != nil {
missing = append(missing, ip)
} else if ip != "unsafe" { // package unsafe is intrinsic
} else {
p.addInput(cu, dep)
}
}
Expand Down
1 change: 1 addition & 0 deletions kythe/go/extractors/govname/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_package_library(

go_test(
name = "govname_test",
size = "small",
srcs = ["govname_test.go"],
library = "govname",
visibility = ["//visibility:private"],
Expand Down
11 changes: 11 additions & 0 deletions kythe/go/extractors/govname/govname.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ func ForBuiltin(signature string) *spb.VName {
}
}

// ForStandardLibrary returns a VName for a standard library package with the
// given import path.
func ForStandardLibrary(importPath string) *spb.VName {
return &spb.VName{
Corpus: golangCorpus,
Language: Language,
Path: importPath,
Signature: "package",
}
}

// IsStandardLibrary reports whether v names part of the Go standard library.
// This includes the "golang.org" corpus but excludes the "golang.org/x/..."
// extension repositories. If v == nil, the answer is false.
Expand Down
19 changes: 19 additions & 0 deletions kythe/go/extractors/govname/govname_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,22 @@ func TestForBuiltin(t *testing.T) {
t.Errorf("ForBuiltin(%q): got %+v, want %+v", signature, got, want)
}
}

func TestForStandardLibrary(t *testing.T) {
tests := []struct {
input string
want *spb.VName
}{
{"fmt", &spb.VName{Corpus: "golang.org", Path: "fmt", Signature: "package", Language: "go"}},
{"io/ioutil", &spb.VName{Corpus: "golang.org", Path: "io/ioutil", Signature: "package", Language: "go"}},
{"strconv", &spb.VName{Corpus: "golang.org", Path: "strconv", Signature: "package", Language: "go"}},
}
for _, test := range tests {
got := ForStandardLibrary(test.input)
if !proto.Equal(got, test.want) {
t.Errorf("ForStandardLibrary(%q): got %+v\nwant %+v", test.input, got, test.want)
} else if !IsStandardLibrary(got) {
t.Errorf("IsStandardLibrary(%+v) is unexpectedly false", got)
}
}
}
5 changes: 5 additions & 0 deletions kythe/go/indexer/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,8 @@ go_indexer_test(
name = "comment_test",
srcs = ["testdata/basic/comments.go"],
)

go_indexer_test(
name = "unsafe_test",
srcs = ["testdata/unsafe.go"],
)
8 changes: 8 additions & 0 deletions kythe/go/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ type packageImporter struct {
func (pi *packageImporter) Import(importPath string) (*types.Package, error) {
if pkg := pi.deps[importPath]; pkg != nil && pkg.Complete() {
return pkg, nil
} else if importPath == "unsafe" {
// The "unsafe" package is special, and isn't usually added by the
// resolver into the dependency map.
pi.deps[importPath] = types.Unsafe
return types.Unsafe, nil
}

// Fetch the required input holding the package for this import path, and
Expand Down Expand Up @@ -235,6 +240,9 @@ func Resolve(unit *apb.CompilationUnit, f Fetcher, info *types.Info) (*PackageIn
pi.PackageVName[pkg].Signature = "package"
}
}
if _, ok := pi.Dependencies["unsafe"]; ok {
pi.PackageVName[types.Unsafe] = govname.ForStandardLibrary("unsafe")
}

// Set this package's own vname.
pi.VName = proto.Clone(unit.VName).(*spb.VName)
Expand Down
11 changes: 11 additions & 0 deletions kythe/go/indexer/testdata/unsafe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Package magic tests resolution of the "unsafe" metapackage.
package magic

//- @"\"unsafe\"" ref/imports Unsafe=vname("package", "golang.org", _, "unsafe", "go")
import "unsafe"

//- @foo defines/binding Foo
//- Foo.node/kind variable
//- @unsafe ref Unsafe
//- @Pointer ref UnsafePointer
var foo unsafe.Pointer

0 comments on commit 0570c4e

Please sign in to comment.