---------- Forwarded message ----------
From: Keynan Pratt <kpr...@atlassian.com>
Date: Sun, Oct 29, 2017 at 5:01 PM
Subject: Re: [go-nuts] go/types#Check is not resolving external package
source positions.
To: roger peppe <rogpe...@gmail.com>


Thanks for the help Roger.

On Sun, Oct 29, 2017 at 5:00 PM, Keynan Pratt <kpr...@atlassian.com> wrote:

> Can confirm the following works as expected:
>
>
> package main
>
> import (
>     "fmt"
>     "go/parser"
>     "go/token"
>     "go/ast"
>     sourceLoader "golang.org/x/tools/go/loader"
> )
>
> func main() {
>     pkgPath := "bitbucket.org/.../test_package"
>     dir := "../..//test_package"
>
>     fset := token.NewFileSet()
>     packages, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
>     if err != nil {
>         fmt.Println(err)
>         return
>     }
>
>     for _, p := range packages {
>         files := make([]*ast.File, 0, 8)
>         for _, file := range p.Files {
>             files = append(files, file)
>         }
>
>         loader := sourceLoader.Config{Fset: fset}
>         loader.CreateFromFiles(pkgPath, files...)
>         prgm, err := loader.Load()
>         if err != nil {
>             fmt.Errorf(err.Error())
>         }
>
>         info := prgm.Created[0].Info
>         fmt.Println("\tUsages from ", pkgPath)
>         for use := range info.Uses {
>             obj := info.Uses[use]
>
>             pkgOfUse := obj.Pkg()
>             nameOfUse := obj.Name()
>             declPos := prgm.Fset.Position(obj.Pos())
>             if pkgOfUse == nil {
>
>                 fmt.Println("Package was nil for obj.id [ ", obj.Id(), " ]")
>                 continue
>             }
>             fmt.Printf(
>                 "\tUsage of %s # %s declared at %s:%d:%d\n",
>                 pkgOfUse.Path(),
>                 nameOfUse,
>                 declPos.Filename, declPos.Line, declPos.Column)
>         }
>     }
> }
>
>
> On Fri, Oct 27, 2017 at 6:28 PM, roger peppe <rogpe...@gmail.com> wrote:
>
>> As I understand it, the default importer used by go/types looks in the
>> intermediate Go object files, which don't have position information,
>> instead of in the source code. This doesn't appear to be made very
>> clear in the stdlib doc comments, but is mentioned by the types
>> tutorial at https://golang.org/s/types-tutorial#imports That tutorial
>> document also says:
>>
>> "The golang.org/tools/x/go/loader package provides an alternative
>> Importer that addresses some of these problems. It loads a complete
>> program from source, performing cgo preprocessing if necessary,
>> followed by parsing and type-checking."
>>
>> As far as I can see, that's not quite right, as that package doesn't
>> seem to define an importer as such, but if you use it, it has an
>> importer internally that reads from source, so I'd suggest using it
>> rather than go/types directly.
>>
>>  I've CC'd Alan Donovan, who can probably expand further on the design
>> choices made here.
>>
>>   cheers,
>>     rog.
>>
>> On 27 October 2017 at 01:51,  <kpr...@atlassian.com> wrote:
>> > I have a simple example file:
>> > ==============================
>> >
>> > package gobbledy_gook
>> >
>> > import (
>> >     "log"
>> >     turtle "github.com/rs/zerolog/log"
>> >     "os"
>> >     "github.com/rs/zerolog"
>> > )
>> >
>> > var LOG = turtle.Logger.Output(os.Stdout).Error()
>> >
>> > func g() []zerolog.Logger {
>> >     return []zerolog.Logger{}
>> > }
>> >
>> > func DoThings()  {
>> >     log.Println("proof of concept")
>> >     g()[3].Error()
>> >     return
>> > }
>> >
>> > ==============================
>> >
>> > I want to use go/ast & go/types to correctly identify the source code
>> > position of the turtle.Logger declaration (.../zerolog/log.go:13:5).
>> >
>> > If I parse only the gobbledy_gook package then the position ends up
>> being
>> > <first file in FileSet>:1:9
>> > If I parse gobbledy_gook & zerolog packages and put them in the fset /
>> list
>> > of files I get an unexpected package error
>> >
>> > Most of the below code is taken from the go/types#Info example code
>> >
>> > func main() {
>> >     files := make([]*ast.File, 0, 8)
>> >     fset := token.NewFileSet()
>> >
>> >     for _, dir := range []string{
>> >         "../../test_package",
>> >         "go/src/github.com/rs/zerolog",
>> >         "go/src/github.com/rs/zerolog/log",
>> >     } {
>> >         packages, err := parser.ParseDir(fset, dir, nil,
>> parser.AllErrors)
>> >         if err != nil {
>> >             fmt.Println(err)
>> >             return
>> >         }
>> >
>> >         for _, p := range packages {
>> >             for _, file := range p.Files {
>> >                 files = append(files, file)
>> >             }
>> >         }
>> >     }
>> >     fmt.Println("Parse complete")
>> >
>> >     info := types.Info{
>> >         Types: make(map[ast.Expr]types.TypeAndValue),
>> >         Defs:  make(map[*ast.Ident]types.Object),
>> >         Uses:  make(map[*ast.Ident]types.Object),
>> >     }
>> >     var conf types.Config = types.Config{Importer: importer.Default()}
>> >     pkg, err := conf.Check("fib", fset, files, &info)
>> >     if err != nil {
>> >         log.Println(err.Error())
>> >     }
>> >     fmt.Println("Check complete")
>> >
>> >     // Print package-level variables in initialization order.
>> >     fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
>> >
>> >     // For each named object, print the line and
>> >     // column of its definition and each of its uses.
>> >     fmt.Println("Defs and Uses of each named object:")
>> >     usesByObj := make(map[types.Object][]string)
>> >     for id, obj := range info.Uses {
>> >         posn := fset.Position(id.Pos())
>> >         lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
>> >         usesByObj[obj] = append(usesByObj[obj], lineCol)
>> >     }
>> >     var items []string
>> >     for obj, uses := range usesByObj {
>> >         sort.Strings(uses)
>> >         item := fmt.Sprintf("%s:\n  defined at %s\n  used at %s",
>> >             types.ObjectString(obj, types.RelativeTo(pkg)),
>> >             fset.Position(obj.Pos()),
>> >             strings.Join(uses, ", "))
>> >         items = append(items, item)
>> >     }
>> >     sort.Strings(items) // sort by line:col, in effect
>> >     fmt.Println(strings.Join(items, "\n"))
>> >     fmt.Println()
>> >
>> >     fmt.Println("Types and Values of each expression:")
>> >     items = nil
>> >     for expr, tv := range info.Types {
>> >         var buf bytes.Buffer
>> >         posn := fset.Position(expr.Pos())
>> >         tvstr := tv.Type.String()
>> >         if tv.Value != nil {
>> >             tvstr += " = " + tv.Value.String()
>> >         }
>> >         // line:col | expr | mode : type = value
>> >         fmt.Fprintf(&buf, "%s:%2d:%2d | %-19s | %s", posn.Filename,
>> >             posn.Line, posn.Column, types.ExprString(expr), tvstr)
>> >         items = append(items, buf.String())
>> >     }
>> >     sort.Strings(items)
>> >     fmt.Println(strings.Join(items, "\n"))
>> > }
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> Groups
>> > "golang-nuts" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> an
>> > email to golang-nuts+unsubscr...@googlegroups.com.
>> > For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to