func WriteInterfaces(dependencies []*types.Package, w io.Writer, merge bool) { allTypeNames := []*types.TypeName{types.New("error").(*types.Named).Obj()} for _, dep := range dependencies { scope := dep.Scope() for _, name := range scope.Names() { if typeName, isTypeName := scope.Lookup(name).(*types.TypeName); isTypeName { allTypeNames = append(allTypeNames, typeName) } } } for _, t := range allTypeNames { if in, isInterface := t.Type().Underlying().(*types.Interface); isInterface { if in.MethodSet().Len() == 0 { continue } implementedBy := make(map[string]bool, 0) for _, other := range allTypeNames { otherType := other.Type() switch otherType.Underlying().(type) { case *types.Interface: // skip case *types.Struct: if types.IsAssignableTo(otherType, in) { implementedBy[fmt.Sprintf("Go$packages[\"%s\"].%s.Go$NonPointer", other.Pkg().Path(), other.Name())] = true } if types.IsAssignableTo(types.NewPointer(otherType), in) { implementedBy[fmt.Sprintf("Go$packages[\"%s\"].%s", other.Pkg().Path(), other.Name())] = true } default: if types.IsAssignableTo(otherType, in) { implementedBy[fmt.Sprintf("Go$packages[\"%s\"].%s", other.Pkg().Path(), other.Name())] = true } if types.IsAssignableTo(types.NewPointer(otherType), in) { implementedBy[fmt.Sprintf("Go$packages[\"%s\"].%s.Go$Pointer", other.Pkg().Path(), other.Name())] = true } } } list := make([]string, 0, len(implementedBy)) for ref := range implementedBy { list = append(list, ref) } sort.Strings(list) var target string switch t.Name() { case "error": target = "Go$error" default: target = fmt.Sprintf("Go$packages[\"%s\"].%s", t.Pkg().Path(), t.Name()) } if merge { for _, entry := range list { fmt.Fprintf(w, "if (%s.Go$implementedBy.indexOf(%s) === -1) { %s.Go$implementedBy.push(%s); }\n", target, entry, target, entry) } continue } fmt.Fprintf(w, "%s.Go$implementedBy = [%s];\n", target, strings.Join(list, ", ")) } } }
func TestNewScopeAndPackage2(t *testing.T) { c := initTestChecker() c.NewScopeAndPackage() c.sc.Insert(types.NewConst(0, c.pkg, "testfloat1", types.New("float64"), exact.MakeFloat64(1))) c.NewScopeAndPackage() for _, name := range c.sc.Names() { if name == "testfloat1" { t.Errorf("scope not reset") } } o := c.sc.Insert(types.NewConst(0, c.pkg, "testfloat1", types.New("float64"), exact.MakeFloat64(2))) if o != nil { t.Errorf("did not reset scope") } }
//insertMetricValues inserts the values and rates of the metrics collected // as constants into the scope used to evaluate the expressions func (c *checker) InsertMetricValuesFromJSON() error { //get metrics from json package //TODO: get directly from metric context if available resp, err := http.Get("http://" + c.hostport + "/api/v1/metrics.json/") if err != nil { return err } defer resp.Body.Close() d := json.NewDecoder(resp.Body) var metrics []metrics.MetricJSON err = d.Decode(&metrics) if err != nil { return err } //insert metric value into scope for _, m := range metrics { switch val := m.Value.(type) { case float64: name := strings.Replace(m.Name, ".", "_", -1) + "_value" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(val))) case map[string]interface{}: //TODO: make sure we don't panic in case something is not formatted // like expected if current, ok := val["current"]; ok { name := strings.Replace(m.Name, ".", "_", -1) + "_current" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(current.(float64)))) } if rate, ok := val["rate"]; ok { name := strings.Replace(m.Name, ".", "_", -1) + "_rate" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(rate.(float64)))) } default: //a value type came up that wasn't anticipated fmt.Fprintln(os.Stderr, reflect.TypeOf(val)) } } return nil }
func (c *checker) InsertMetricValuesFromContext(m *metrics.MetricContext) error { for metricName, metric := range m.Gauges { name := strings.Replace(metricName, ".", "_", -1) + "_value" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(metric.Get()))) sname := name + "_string" c.sc.Insert(types.NewConst(0, c.pkg, sname, types.New("string"), exact.MakeString(fmt.Sprintf("%0.2f", metric.Get())))) } for metricName, metric := range m.Counters { name := strings.Replace(metricName, ".", "_", -1) + "_current" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeUint64(metric.Get()))) sname := name + "_string" c.sc.Insert(types.NewConst(0, c.pkg, sname, types.New("string"), exact.MakeString(fmt.Sprintf("%d", metric.Get())))) name = strings.Replace(metricName, ".", "_", -1) + "_rate" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(metric.ComputeRate()))) } return nil }
func WriteProgramCode(pkgs []*Archive, importContext *ImportContext, w *SourceMapFilter) { mainPkg := pkgs[len(pkgs)-1] minify := mainPkg.Minified declsByObject := make(map[string][]*Decl) var pendingDecls []*Decl for _, pkg := range pkgs { for i := range pkg.Declarations { d := &pkg.Declarations[i] if len(d.DceFilters) == 0 { pendingDecls = append(pendingDecls, d) continue } for _, f := range d.DceFilters { o := string(pkg.ImportPath) + ":" + string(f) declsByObject[o] = append(declsByObject[o], d) } } } for len(pendingDecls) != 0 { d := pendingDecls[len(pendingDecls)-1] pendingDecls = pendingDecls[:len(pendingDecls)-1] for _, dep := range d.DceDeps { o := string(dep) if decls, ok := declsByObject[o]; ok { delete(declsByObject, o) name := strings.Split(o, ":")[1] for _, d := range decls { for i, f := range d.DceFilters { if string(f) == name { d.DceFilters[i] = d.DceFilters[len(d.DceFilters)-1] d.DceFilters = d.DceFilters[:len(d.DceFilters)-1] break } } if len(d.DceFilters) == 0 { pendingDecls = append(pendingDecls, d) } } } } } w.Write([]byte("\"use strict\";\n(function() {\n\n")) w.Write(removeWhitespace([]byte(strings.TrimSpace(prelude)), minify)) w.Write([]byte("\n")) // write packages for _, pkg := range pkgs { WritePkgCode(pkg, minify, w) } // write interfaces allTypeNames := []*types.TypeName{types.New("error").(*types.Named).Obj()} for _, pkg := range pkgs { scope := importContext.Packages[string(pkg.ImportPath)].Scope() for _, name := range scope.Names() { if typeName, isTypeName := scope.Lookup(name).(*types.TypeName); isTypeName { if _, notUsed := declsByObject[string(pkg.ImportPath)+":"+name]; !notUsed { allTypeNames = append(allTypeNames, typeName) } } } } for _, t := range allTypeNames { if in, isInterface := t.Type().Underlying().(*types.Interface); isInterface { if in.Empty() { continue } implementedBy := make(map[string]bool, 0) for _, other := range allTypeNames { otherType := other.Type() switch otherType.Underlying().(type) { case *types.Interface: // skip case *types.Struct: if types.AssignableTo(otherType, in) { implementedBy[fmt.Sprintf("$packages[\"%s\"].%s", other.Pkg().Path(), other.Name())] = true } if types.AssignableTo(types.NewPointer(otherType), in) { implementedBy[fmt.Sprintf("$packages[\"%s\"].%s.Ptr", other.Pkg().Path(), other.Name())] = true } default: if types.AssignableTo(otherType, in) { implementedBy[fmt.Sprintf("$packages[\"%s\"].%s", other.Pkg().Path(), other.Name())] = true } if types.AssignableTo(types.NewPointer(otherType), in) { implementedBy[fmt.Sprintf("$ptrType($packages[\"%s\"].%s)", other.Pkg().Path(), other.Name())] = true } } } list := make([]string, 0, len(implementedBy)) for ref := range implementedBy { list = append(list, ref) } sort.Strings(list) var target string switch t.Name() { case "error": target = "$error" default: target = fmt.Sprintf("$packages[\"%s\"].%s", t.Pkg().Path(), t.Name()) } w.Write(removeWhitespace([]byte(fmt.Sprintf("%s.implementedBy = [%s];\n", target, strings.Join(list, ", "))), minify)) } } for _, pkg := range pkgs { w.Write([]byte("$packages[\"" + string(pkg.ImportPath) + "\"].init();\n")) } w.Write([]byte("$packages[\"" + string(mainPkg.ImportPath) + "\"].main();\n\n})();\n")) }
actual = actual.Underlying() } if actual == nil { // No type information available. Assume true, so we do the check. return true, "" } switch actual.(type) { case *types.Struct: return true, typ.String() default: return false, "" } } var ( stringerMethodType = types.New("func() string") errorType = types.New("interface{ Error() string }").(*types.Interface) stringerType = types.New("interface{ String() string }").(*types.Interface) // One day this might work. See issue 6259. // formatterType = types.New("interface{Format(f fmt.State, c rune)}") ) // matchArgType reports an error if printf verb t is not appropriate // for operand arg. // // typ is used only for recursive calls; external callers must supply nil. // // (Recursion arises from the compound types {map,chan,slice} which // may be printed with %d etc. if that is appropriate for their element // types.) func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool {
package main import ( "go/ast" "go/token" "code.google.com/p/go.tools/go/types" ) // imports is the canonical map of imported packages we need for typechecking. // It is created during initialization. var imports = make(map[string]*types.Package) var ( stringerMethodType = types.New("func() string") errorType = types.New("error").Underlying().(*types.Interface) stringerType = types.New("interface{ String() string }").(*types.Interface) formatterType *types.Interface ) func init() { typ := importType("fmt", "Formatter") if typ != nil { formatterType = typ.Underlying().(*types.Interface) } } // importType returns the type denoted by the qualified identifier // path.name, and adds the respective package to the imports map // as a side effect.