This library are not supposed to be used that way. Importer should be used
directly:
package main
import (
"fmt"
"go/importer"
"go/types"
)
var imprt = importer.For("source", nil)
func main() {
p1, err := imprt.Import("awesome/pkg1")
if err != nil {
panic(err)
}
p2, err := imprt.Import("awesome/pkg2")
if err != nil {
panic(err)
}
iface :=
p1.Scope().Lookup("Interface").(*types.TypeName).Type().(*types.Named).Underlying().(*types.Interface)
impl1 := p1.Scope().Lookup("Implementation1").Type()
fmt.Printf("%s\n", impl1.(*types.Named).Method(0).Name())
impl2 := p2.Scope().Lookup("Implementation2").Type()
fmt.Println("Implementation1 implements Interface", types.Implements(impl1,
iface))
fmt.Println("Implementation2 implements Interface", types.Implements(impl2,
iface))
}
Введите код...
The problem though ASTs are not cached. I copied implementation of importer
from go/internal/srcimporter and extended it with caching (I need ASTs
besides *type.Package for style checks)
суббота, 5 мая 2018 г., 2:04:34 UTC+3 пользователь Denis Cheremisov написал:
>
> Hi!
>
> I am writing a special linting-like piece of code and struggle dealing
> with the Implements <https://golang.org/pkg/go/types/#Implements> that
> doesn't work for my configuration. I made a simplified testing example to
> show the issue:
>
>
> - I have package speaker with interface Speaker and its default
> implementation.
>
> package speaker
> type Default struct{}
> func (Default) Speak(Arg) string {
> return "speak"
> }
> type Arg struct{}
> type Speaker interface {
> Speak(Arg) string
> }
>
> -
>
> Now, I have another package, with "Russian speaker":
>
>
> package ru
> import "awesome/speaker"
> type Russian struct{}
> func (Russian) Speak(speaker.Arg) string {
> return "говорить"
> }
>
> -
>
> An finally I have a main package
>
>
> package main
>
> import (
> "fmt"
> "go/ast"
> "go/importer"
> "go/parser"
> "go/token"
> "go/types"
> "path/filepath"
> "runtime"
> )
>
> func getPath() string {
> fpcs := make([]uintptr, 5)
> frameIter := runtime.CallersFrames(fpcs[:runtime.Callers(1, fpcs)])
> var frames []runtime.Frame
> frame, more := frameIter.Next()
> frames = append(frames, frame)
> if !more {
> panic("stack frames must exists for a call")
> }
> return filepath.Dir(frame.File)
> }
>
> func getTypes(path ...string) *types.Package {
> path = append([]string{getPath()}, path...)
> fullpath := filepath.Join(path...)
> fset := token.NewFileSet()
> pkgs, err := parser.ParseDir(fset, fullpath, nil, parser.ParseComments)
> if err != nil {
> panic(err)
> }
> for _, pkg := range pkgs {
> config := &types.Config{
> IgnoreFuncBodies: false,
> FakeImportC: false,
> Error: nil,
> Importer: importer.Default(),
> Sizes: nil,
> DisableUnusedImportCheck: false,
> }
> info := types.Info{
> Types: map[ast.Expr]types.TypeAndValue{},
> Defs: map[*ast.Ident]types.Object{},
> Uses: map[*ast.Ident]types.Object{},
> }
> var files []*ast.File
> for _, file := range pkg.Files {
> files = append(files, file)
> }
> typeInfo, err := config.Check(fullpath, fset, files, &info)
> if err != nil {
> panic(err)
> }
> return typeInfo
> }
> return nil
> }
>
> func main() {
> mainPkg := getTypes("speaker")
> ruPkg := getTypes("ru")
>
> iface :=
> mainPkg.Scope().Lookup("Speaker").Type().Underlying().(*types.Interface)
> dflt := mainPkg.Scope().Lookup("Default").Type()
> russian := ruPkg.Scope().Lookup("Russian").Type()
>
> fmt.Println(types.Implements(dflt, iface))
> fmt.Println(types.Implements(russian, iface))
> }
>
>
> Output is:
> true
> false
>
> The output is true-true without the argument. Is it a feature or a bug?
> How can I walk around it?
>
--
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 [email protected].
For more options, visit https://groups.google.com/d/optout.