1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8	"go/ast"
9	"strconv"
10)
11
12func init() {
13	register(gotypesFix)
14}
15
16var gotypesFix = fix{
17	name: "gotypes",
18	date: "2015-07-16",
19	f:    gotypes,
20	desc: `Change imports of golang.org/x/tools/go/{exact,types} to go/{constant,types}`,
21}
22
23func gotypes(f *ast.File) bool {
24	fixed := fixGoTypes(f)
25	if fixGoExact(f) {
26		fixed = true
27	}
28	return fixed
29}
30
31func fixGoTypes(f *ast.File) bool {
32	return rewriteImport(f, "golang.org/x/tools/go/types", "go/types")
33}
34
35func fixGoExact(f *ast.File) bool {
36	// This one is harder because the import name changes.
37	// First find the import spec.
38	var importSpec *ast.ImportSpec
39	walk(f, func(n any) {
40		if importSpec != nil {
41			return
42		}
43		spec, ok := n.(*ast.ImportSpec)
44		if !ok {
45			return
46		}
47		path, err := strconv.Unquote(spec.Path.Value)
48		if err != nil {
49			return
50		}
51		if path == "golang.org/x/tools/go/exact" {
52			importSpec = spec
53		}
54
55	})
56	if importSpec == nil {
57		return false
58	}
59
60	// We are about to rename exact.* to constant.*, but constant is a common
61	// name. See if it will conflict. This is a hack but it is effective.
62	exists := renameTop(f, "constant", "constant")
63	suffix := ""
64	if exists {
65		suffix = "_"
66	}
67	// Now we need to rename all the uses of the import. RewriteImport
68	// affects renameTop, but not vice versa, so do them in this order.
69	renameTop(f, "exact", "constant"+suffix)
70	rewriteImport(f, "golang.org/x/tools/go/exact", "go/constant")
71	// renameTop will also rewrite the imported package name. Fix that;
72	// we know it should be missing.
73	importSpec.Name = nil
74	return true
75}
76