blob: 610ab44c62459fd41dbc52096d5d1786b69fcc27 [file] [log] [blame]
// 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)))
}
}