// Copyright 2013 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 or at // https://developers.google.com/open-source/licenses/bsd. package doc import ( "fmt" "go/ast" "go/token" "strconv" "strings" "github.com/golang/gddo/gosrc" ) // This list of deprecated exports is used to find code that has not been // updated for Go 1. var deprecatedExports = map[string][]string{ `"bytes"`: {"Add"}, `"crypto/aes"`: {"Cipher"}, `"crypto/hmac"`: {"NewSHA1", "NewSHA256"}, `"crypto/rand"`: {"Seed"}, `"encoding/json"`: {"MarshalForHTML"}, `"encoding/xml"`: {"Marshaler", "NewParser", "Parser"}, `"html"`: {"NewTokenizer", "Parse"}, `"image"`: {"Color", "NRGBAColor", "RGBAColor"}, `"io"`: {"Copyn"}, `"log"`: {"Exitf"}, `"math"`: {"Fabs", "Fmax", "Fmod"}, `"os"`: {"Envs", "Error", "Getenverror", "NewError", "Time", "UnixSignal", "Wait"}, `"reflect"`: {"MapValue", "Typeof"}, `"runtime"`: {"UpdateMemStats"}, `"strconv"`: {"Atob", "Atof32", "Atof64", "AtofN", "Atoi64", "Atoui", "Atoui64", "Btoui64", "Ftoa64", "Itoa64", "Uitoa", "Uitoa64"}, `"time"`: {"LocalTime", "Nanoseconds", "NanosecondsToLocalTime", "Seconds", "SecondsToLocalTime", "SecondsToUTC"}, `"unicode/utf8"`: {"NewString"}, } type vetVisitor struct { errors map[string]token.Pos } func (v *vetVisitor) Visit(n ast.Node) ast.Visitor { if sel, ok := n.(*ast.SelectorExpr); ok { if x, _ := sel.X.(*ast.Ident); x != nil { if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg { if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil { for _, name := range deprecatedExports[spec.Path.Value] { if name == sel.Sel.Name { v.errors[fmt.Sprintf("%s.%s not found", spec.Path.Value, sel.Sel.Name)] = n.Pos() return nil } } } } } } return v } func (b *builder) vetPackage(pkg *Package, apkg *ast.Package) { errors := make(map[string]token.Pos) for _, file := range apkg.Files { for _, is := range file.Imports { importPath, _ := strconv.Unquote(is.Path.Value) if !gosrc.IsValidPath(importPath) && !strings.HasPrefix(importPath, "exp/") && !strings.HasPrefix(importPath, "appengine") { errors[fmt.Sprintf("Unrecognized import path %q", importPath)] = is.Pos() } } v := vetVisitor{errors: errors} ast.Walk(&v, file) } for message, pos := range errors { pkg.Errors = append(pkg.Errors, fmt.Sprintf("%s (%s)", message, b.fset.Position(pos))) } }