Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
ae2d4b3c
Commit
ae2d4b3c
authored
Jan 05, 2017
by
deads2k
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bump(k8s.io/gengo): 8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
parent
8ef69025
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
298 additions
and
230 deletions
+298
-230
Godeps.json
Godeps/Godeps.json
+10
-10
deepcopy.go
...k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go
+82
-41
defaulter.go
...s.io/gengo/examples/defaulter-gen/generators/defaulter.go
+0
-1
byte.go
vendor/k8s.io/gengo/examples/set-gen/sets/byte.go
+1
-1
doc.go
vendor/k8s.io/gengo/examples/set-gen/sets/doc.go
+1
-1
empty.go
vendor/k8s.io/gengo/examples/set-gen/sets/empty.go
+1
-1
int.go
vendor/k8s.io/gengo/examples/set-gen/sets/int.go
+1
-1
int64.go
vendor/k8s.io/gengo/examples/set-gen/sets/int64.go
+1
-1
string.go
vendor/k8s.io/gengo/examples/set-gen/sets/string.go
+1
-1
parse.go
vendor/k8s.io/gengo/parser/parse.go
+200
-172
No files found.
Godeps/Godeps.json
View file @
ae2d4b3c
...
...
@@ -2669,43 +2669,43 @@
},
{
"ImportPath"
:
"k8s.io/gengo/args"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/examples/deepcopy-gen/generators"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/examples/defaulter-gen/generators"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/examples/import-boss/generators"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/examples/set-gen/generators"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/examples/set-gen/sets"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/generator"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/namer"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/parser"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/gengo/types"
,
"Rev"
:
"
6a1c24d7f08e671c244023ca9367d2dfbfaf57fc
"
"Rev"
:
"
8dd9c9e5e82c3cca687497c3cd7ac90e702c7c21
"
},
{
"ImportPath"
:
"k8s.io/heapster/metrics/api/v1/types"
,
...
...
vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go
View file @
ae2d4b3c
...
...
@@ -124,14 +124,16 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
inputs
:=
sets
.
NewString
(
context
.
Inputs
...
)
packages
:=
generator
.
Packages
{}
header
:=
append
([]
byte
(
fmt
.
Sprintf
(
"// +build !%s
\n\n
"
,
arguments
.
GeneratedBuildTag
)),
boilerplate
...
)
header
=
append
(
header
,
[]
byte
(
`
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
header
=
append
(
header
,
[]
byte
(
`
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
`
)
...
)
`
)
...
)
boundingDirs
:=
[]
string
{}
if
customArgs
,
ok
:=
arguments
.
CustomArgs
.
(
*
CustomArgs
);
ok
{
if
customArgs
.
BoundingDirs
==
nil
{
customArgs
.
BoundingDirs
=
context
.
Inputs
}
for
i
:=
range
customArgs
.
BoundingDirs
{
// Strip any trailing slashes - they are not exactly "correct" but
// this is friendlier.
...
...
@@ -140,7 +142,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
for
i
:=
range
inputs
{
glog
.
V
(
5
)
.
Infof
(
"
c
onsidering pkg %q"
,
i
)
glog
.
V
(
5
)
.
Infof
(
"
C
onsidering pkg %q"
,
i
)
pkg
:=
context
.
Universe
[
i
]
if
pkg
==
nil
{
// If the input had no Go files, for example.
...
...
@@ -181,16 +183,16 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
if
pkgNeedsGeneration
{
glog
.
V
(
3
)
.
Infof
(
"Package %q needs generation"
,
i
)
packages
=
append
(
packages
,
&
generator
.
DefaultPackage
{
PackageName
:
strings
.
Split
(
filepath
.
Base
(
pkg
.
Path
),
"."
)[
0
],
PackagePath
:
pkg
.
Path
,
HeaderText
:
header
,
GeneratorFunc
:
func
(
c
*
generator
.
Context
)
(
generators
[]
generator
.
Generator
)
{
generators
=
[]
generator
.
Generator
{}
generators
=
append
(
generators
,
NewGenDeepCopy
(
arguments
.
OutputFileBaseName
,
pkg
.
Path
,
boundingDirs
,
(
ptagValue
==
tagValuePackage
),
ptagRegister
))
return
generators
return
[]
generator
.
Generator
{
NewGenDeepCopy
(
arguments
.
OutputFileBaseName
,
pkg
.
Path
,
boundingDirs
,
(
ptagValue
==
tagValuePackage
),
ptagRegister
),
}
},
FilterFunc
:
func
(
c
*
generator
.
Context
,
t
*
types
.
Type
)
bool
{
return
t
.
Name
.
Package
==
pkg
.
Path
...
...
@@ -202,7 +204,6 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
const
(
apiPackagePath
=
"k8s.io/kubernetes/pkg/api"
conversionPackagePath
=
"k8s.io/kubernetes/pkg/conversion"
runtimePackagePath
=
"k8s.io/kubernetes/pkg/runtime"
)
...
...
@@ -253,11 +254,16 @@ func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool {
enabled
=
true
}
}
copyable
:=
enabled
&&
copyableType
(
t
)
if
copyable
{
g
.
typesForInit
=
append
(
g
.
typesForInit
,
t
)
if
!
enabled
{
return
false
}
return
copyable
if
!
copyableType
(
t
)
{
glog
.
V
(
2
)
.
Infof
(
"Type %v is not copyable"
,
t
)
return
false
}
glog
.
V
(
4
)
.
Infof
(
"Type %v is copyable"
,
t
)
g
.
typesForInit
=
append
(
g
.
typesForInit
,
t
)
return
true
}
func
(
g
*
genDeepCopy
)
copyableAndInBounds
(
t
*
types
.
Type
)
bool
{
...
...
@@ -368,12 +374,20 @@ func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
cloner
:=
c
.
Universe
.
Type
(
types
.
Name
{
Package
:
conversionPackagePath
,
Name
:
"Cloner"
})
g
.
imports
.
AddType
(
cloner
)
if
!
g
.
registerTypes
{
// TODO: We should come up with a solution to register all generated
// deep-copy functions. However, for now, to avoid import cycles
// we register only those explicitly requested.
return
nil
sw
:=
generator
.
NewSnippetWriter
(
w
,
c
,
"$"
,
"$"
)
sw
.
Do
(
"// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them.
\n
"
,
nil
)
sw
.
Do
(
"func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc{
\n
"
,
nil
)
sw
.
Do
(
"return []conversion.GeneratedDeepCopyFunc{
\n
"
,
nil
)
for
_
,
t
:=
range
g
.
typesForInit
{
args
:=
argsFromType
(
t
)
.
With
(
"typeof"
,
c
.
Universe
.
Package
(
"reflect"
)
.
Function
(
"TypeOf"
))
sw
.
Do
(
"{Fn: $.type|dcFnName$, InType: $.typeof|raw$(&$.type|raw${})},
\n
"
,
args
)
}
sw
.
Do
(
"}
\n
"
,
nil
)
sw
.
Do
(
"}
\n\n
"
,
nil
)
return
sw
.
Error
()
}
glog
.
V
(
5
)
.
Infof
(
"
r
egistering types in pkg %q"
,
g
.
targetPackage
)
glog
.
V
(
5
)
.
Infof
(
"
R
egistering types in pkg %q"
,
g
.
targetPackage
)
sw
:=
generator
.
NewSnippetWriter
(
w
,
c
,
"$"
,
"$"
)
sw
.
Do
(
"func init() {
\n
"
,
nil
)
...
...
@@ -410,12 +424,12 @@ func (g *genDeepCopy) needsGeneration(t *types.Type) bool {
}
if
g
.
allTypes
&&
tv
==
"false"
{
// The whole package is being generated, but this type has opted out.
glog
.
V
(
5
)
.
Infof
(
"
n
ot generating for type %v because type opted out"
,
t
)
glog
.
V
(
5
)
.
Infof
(
"
N
ot generating for type %v because type opted out"
,
t
)
return
false
}
if
!
g
.
allTypes
&&
tv
!=
"true"
{
// The whole package is NOT being generated, and this type has NOT opted in.
glog
.
V
(
5
)
.
Infof
(
"
n
ot generating for type %v because type did not opt in"
,
t
)
glog
.
V
(
5
)
.
Infof
(
"
N
ot generating for type %v because type did not opt in"
,
t
)
return
false
}
return
true
...
...
@@ -425,7 +439,7 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri
if
!
g
.
needsGeneration
(
t
)
{
return
nil
}
glog
.
V
(
5
)
.
Infof
(
"
generating
for type %v"
,
t
)
glog
.
V
(
5
)
.
Infof
(
"
Generating deepcopy function
for type %v"
,
t
)
sw
:=
generator
.
NewSnippetWriter
(
w
,
c
,
"$"
,
"$"
)
args
:=
argsFromType
(
t
)
.
...
...
@@ -535,12 +549,18 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
}
func
(
g
*
genDeepCopy
)
doStruct
(
t
*
types
.
Type
,
sw
*
generator
.
SnippetWriter
)
{
if
len
(
t
.
Members
)
==
0
{
// at least do something with in/out to avoid "declared and not used" errors
sw
.
Do
(
"_ = in
\n
_ = out
\n
"
,
nil
)
if
hasDeepCopyMethod
(
t
)
{
sw
.
Do
(
"*out = in.DeepCopy()
\n
"
,
nil
)
return
}
// Simple copy covers a lot of cases.
sw
.
Do
(
"*out = *in
\n
"
,
nil
)
// Now fix-up fields as needed.
for
_
,
m
:=
range
t
.
Members
{
t
:=
m
.
Type
hasMethod
:=
hasDeepCopyMethod
(
t
)
if
t
.
Kind
==
types
.
Alias
{
copied
:=
*
t
.
Underlying
copied
.
Name
=
t
.
Name
...
...
@@ -548,28 +568,40 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
}
args
:=
generator
.
Args
{
"type"
:
t
,
"kind"
:
t
.
Kind
,
"name"
:
m
.
Name
,
}
switch
t
.
Kind
{
case
types
.
Builtin
:
sw
.
Do
(
"out.$.name$ = in.$.name$
\n
"
,
args
)
if
hasMethod
{
sw
.
Do
(
"out.$.name$ = in.$.name$.DeepCopy()
\n
"
,
args
)
}
case
types
.
Map
,
types
.
Slice
,
types
.
Pointer
:
sw
.
Do
(
"if in.$.name$ != nil {
\n
"
,
args
)
sw
.
Do
(
"in, out := &in.$.name$, &out.$.name$
\n
"
,
args
)
g
.
generateFor
(
t
,
sw
)
sw
.
Do
(
"} else {
\n
"
,
nil
)
sw
.
Do
(
"out.$.name$ = nil
\n
"
,
args
)
sw
.
Do
(
"}
\n
"
,
nil
)
if
hasMethod
{
sw
.
Do
(
"if in.$.name$ != nil {
\n
"
,
args
)
sw
.
Do
(
"out.$.name$ = in.$.name$.DeepCopy()
\n
"
,
args
)
sw
.
Do
(
"}
\n
"
,
nil
)
}
else
{
// Fixup non-nil reference-sematic types.
sw
.
Do
(
"if in.$.name$ != nil {
\n
"
,
args
)
sw
.
Do
(
"in, out := &in.$.name$, &out.$.name$
\n
"
,
args
)
g
.
generateFor
(
t
,
sw
)
sw
.
Do
(
"}
\n
"
,
nil
)
}
case
types
.
Struct
:
if
has
DeepCopyMethod
(
t
)
{
if
has
Method
{
sw
.
Do
(
"out.$.name$ = in.$.name$.DeepCopy()
\n
"
,
args
)
}
else
if
t
.
IsAssignable
()
{
sw
.
Do
(
"out.$.name$ = in.$.name$
\n
"
,
args
)
// Nothing else needed.
}
else
if
g
.
copyableAndInBounds
(
t
)
{
// Not assignable but should have a deepcopy function.
// TODO: do a topological sort of packages and ensure that this works, else inline it.
sw
.
Do
(
"if err := $.type|dcFnName$(&in.$.name$, &out.$.name$, c); err != nil {
\n
"
,
args
)
sw
.
Do
(
"return err
\n
"
,
nil
)
sw
.
Do
(
"}
\n
"
,
nil
)
}
else
{
// Fall back on the slow-path and hope it works.
// TODO: don't depend on kubernetes code for this
sw
.
Do
(
"if newVal, err := c.DeepCopy(&in.$.name$); err != nil {
\n
"
,
args
)
sw
.
Do
(
"return err
\n
"
,
nil
)
sw
.
Do
(
"} else {
\n
"
,
nil
)
...
...
@@ -577,13 +609,22 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
sw
.
Do
(
"}
\n
"
,
nil
)
}
default
:
sw
.
Do
(
"if in.$.name$ == nil {
\n
"
,
args
)
sw
.
Do
(
"out.$.name$ = nil
\n
"
,
args
)
sw
.
Do
(
"} else if newVal, err := c.DeepCopy(&in.$.name$); err != nil {
\n
"
,
args
)
sw
.
Do
(
"return err
\n
"
,
nil
)
sw
.
Do
(
"} else {
\n
"
,
nil
)
sw
.
Do
(
"out.$.name$ = *newVal.(*$.type|raw$)
\n
"
,
args
)
sw
.
Do
(
"}
\n
"
,
nil
)
// Interfaces, Arrays, and other Kinds we don't understand.
sw
.
Do
(
"// in.$.name$ is kind '$.kind$'
\n
"
,
args
)
if
hasMethod
{
sw
.
Do
(
"if in.$.name$ != nil {
\n
"
,
args
)
sw
.
Do
(
"out.$.name$ = in.$.name$.DeepCopy()
\n
"
,
args
)
sw
.
Do
(
"}
\n
"
,
args
)
}
else
{
// TODO: don't depend on kubernetes code for this
sw
.
Do
(
"if in.$.name$ != nil {
\n
"
,
args
)
sw
.
Do
(
"if newVal, err := c.DeepCopy(&in.$.name$); err != nil {
\n
"
,
args
)
sw
.
Do
(
"return err
\n
"
,
nil
)
sw
.
Do
(
"} else {
\n
"
,
nil
)
sw
.
Do
(
"out.$.name$ = *newVal.(*$.type|raw$)
\n
"
,
args
)
sw
.
Do
(
"}
\n
"
,
nil
)
sw
.
Do
(
"}
\n
"
,
nil
)
}
}
}
}
...
...
vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go
View file @
ae2d4b3c
...
...
@@ -323,7 +323,6 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
if
len
(
newDefaulters
)
==
0
{
glog
.
V
(
5
)
.
Infof
(
"no defaulters in package %s"
,
pkg
.
Name
)
continue
}
packages
=
append
(
packages
,
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/byte.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/doc.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/empty.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/int.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/int64.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/examples/set-gen/sets/string.go
View file @
ae2d4b3c
/*
Copyright 201
6
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
vendor/k8s.io/gengo/parser/parse.go
View file @
ae2d4b3c
...
...
@@ -33,30 +33,38 @@ import (
"k8s.io/gengo/types"
)
// This clarifies when a pkg path has been canonicalized.
type
importPathString
string
// Builder lets you add all the go files in all the packages that you care
// about, then constructs the type source data.
type
Builder
struct
{
context
*
build
.
Context
buildInfo
map
[
string
]
*
build
.
Package
context
*
build
.
Context
// Map of package names to more canonical information about the package.
// This might hold the same value for multiple names, e.g. if someone
// referenced ./pkg/name or in the case of vendoring, which canonicalizes
// differently that what humans would type.
buildPackages
map
[
string
]
*
build
.
Package
fset
*
token
.
FileSet
// map of package
id
to list of parsed files
parsed
map
[
s
tring
][]
parsedFile
// map of package
id
to absolute path (to prevent overlap)
absPaths
map
[
s
tring
]
string
// map of package
path
to list of parsed files
parsed
map
[
importPathS
tring
][]
parsedFile
// map of package
path
to absolute path (to prevent overlap)
absPaths
map
[
importPathS
tring
]
string
// Set by
makePackage(), used by importer
() and friends.
pkgs
map
[
s
tring
]
*
tc
.
Package
// Set by
typeCheckPackage(), used by importPackage
() and friends.
typeCheckedPackages
map
[
importPathS
tring
]
*
tc
.
Package
// Map of package path to whether the user requested it or it was from
// an import.
userRequested
map
[
s
tring
]
bool
userRequested
map
[
importPathS
tring
]
bool
// All comments from everywhere in every parsed file.
endLineToCommentGroup
map
[
fileLine
]
*
ast
.
CommentGroup
// map of package to list of packages it imports.
importGraph
map
[
s
tring
]
map
[
string
]
struct
{}
importGraph
map
[
importPathS
tring
]
map
[
string
]
struct
{}
}
// parsedFile is for tracking files with name
...
...
@@ -87,13 +95,14 @@ func New() *Builder {
c
.
CgoEnabled
=
false
return
&
Builder
{
context
:
&
c
,
buildInfo
:
map
[
string
]
*
build
.
Package
{},
buildPackages
:
map
[
string
]
*
build
.
Package
{},
typeCheckedPackages
:
map
[
importPathString
]
*
tc
.
Package
{},
fset
:
token
.
NewFileSet
(),
parsed
:
map
[
s
tring
][]
parsedFile
{},
absPaths
:
map
[
s
tring
]
string
{},
userRequested
:
map
[
s
tring
]
bool
{},
parsed
:
map
[
importPathS
tring
][]
parsedFile
{},
absPaths
:
map
[
importPathS
tring
]
string
{},
userRequested
:
map
[
importPathS
tring
]
bool
{},
endLineToCommentGroup
:
map
[
fileLine
]
*
ast
.
CommentGroup
{},
importGraph
:
map
[
s
tring
]
map
[
string
]
struct
{}{},
importGraph
:
map
[
importPathS
tring
]
map
[
string
]
struct
{}{},
}
}
...
...
@@ -105,71 +114,73 @@ func (b *Builder) AddBuildTags(tags ...string) {
// Get package information from the go/build package. Automatically excludes
// e.g. test files and files for other platforms-- there is quite a bit of
// logic of that nature in the build package.
func
(
b
*
Builder
)
buildPackage
(
pkgPath
string
)
(
*
build
.
Package
,
error
)
{
// This is a bit of a hack. The srcDir argument to Import() should
// properly be the dir of the file which depends on the package to be
// imported, so that vendoring can work properly. We assume that there is
// only one level of vendoring, and that the CWD is inside the GOPATH, so
// this should be safe.
cwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"unable to get current directory: %v"
,
err
)
func
(
b
*
Builder
)
importBuildPackage
(
dir
string
)
(
*
build
.
Package
,
error
)
{
if
buildPkg
,
ok
:=
b
.
buildPackages
[
dir
];
ok
{
return
buildPkg
,
nil
}
// First, find it, so we know what path to use.
pkg
,
err
:=
b
.
context
.
Import
(
pkgPath
,
cwd
,
build
.
FindOnly
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"unable to *find* %q: %v"
,
pkgPath
,
err
)
}
pkgPath
=
pkg
.
ImportPath
if
pkg
,
ok
:=
b
.
buildInfo
[
pkgPath
];
ok
{
return
pkg
,
nil
}
pkg
,
err
=
b
.
context
.
Import
(
pkgPath
,
cwd
,
build
.
ImportComment
)
// This validates the `package foo // github.com/bar/foo` comments.
buildPkg
,
err
:=
b
.
importWithMode
(
dir
,
build
.
ImportComment
)
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
build
.
NoGoError
);
!
ok
{
return
nil
,
fmt
.
Errorf
(
"unable to import %q: %v"
,
pkgPath
,
err
)
return
nil
,
fmt
.
Errorf
(
"unable to import %q: %v"
,
dir
,
err
)
}
}
b
.
buildInfo
[
pkgPath
]
=
pkg
if
b
.
importGraph
[
pkgPath
]
==
nil
{
b
.
importGraph
[
pkgPath
]
=
map
[
string
]
struct
{}{}
if
buildPkg
==
nil
{
// Might be an empty directory. Try to just find the dir.
buildPkg
,
err
=
b
.
importWithMode
(
dir
,
build
.
FindOnly
)
if
err
!=
nil
{
return
nil
,
err
}
}
for
_
,
p
:=
range
pkg
.
Imports
{
b
.
importGraph
[
pkgPath
][
p
]
=
struct
{}{}
// Remember it under the user-provided name.
glog
.
V
(
5
)
.
Infof
(
"saving buildPackage %s"
,
dir
)
b
.
buildPackages
[
dir
]
=
buildPkg
if
dir
!=
buildPkg
.
ImportPath
{
// Since `dir` is not the canonical name, see if we knew it under another name.
if
buildPkg
,
ok
:=
b
.
buildPackages
[
buildPkg
.
ImportPath
];
ok
{
return
buildPkg
,
nil
}
// Must be new, save it under the canonical name, too.
glog
.
V
(
5
)
.
Infof
(
"saving buildPackage %s"
,
buildPkg
.
ImportPath
)
b
.
buildPackages
[
buildPkg
.
ImportPath
]
=
buildPkg
}
return
pkg
,
nil
return
buildPkg
,
nil
}
// AddFile adds a file to the set. The pkg must be of the form
// "canonical/pkg/path" and the path must be the absolute path to the file.
func
(
b
*
Builder
)
AddFile
(
pkg
string
,
path
string
,
src
[]
byte
)
error
{
return
b
.
addFile
(
pkg
,
path
,
src
,
true
)
// AddFileForTest adds a file to the set, without verifying that the provided
// pkg actually exists on disk. The pkg must be of the form "canonical/pkg/path"
// and the path must be the absolute path to the file. Because this bypasses
// the normal recursive finding of package dependencies (on disk), test should
// sort their test files topologically first, so all deps are resolved by the
// time we need them.
func
(
b
*
Builder
)
AddFileForTest
(
pkg
string
,
path
string
,
src
[]
byte
)
error
{
if
err
:=
b
.
addFile
(
importPathString
(
pkg
),
path
,
src
,
true
);
err
!=
nil
{
return
err
}
if
_
,
err
:=
b
.
typeCheckPackage
(
importPathString
(
pkg
));
err
!=
nil
{
return
err
}
return
nil
}
// addFile adds a file to the set. The pkg must be of the form
// addFile adds a file to the set. The pkg
Path
must be of the form
// "canonical/pkg/path" and the path must be the absolute path to the file. A
// flag indicates whether this file was user-requested or just from following
// the import graph.
func
(
b
*
Builder
)
addFile
(
pkg
string
,
path
string
,
src
[]
byte
,
userRequested
bool
)
error
{
func
(
b
*
Builder
)
addFile
(
pkgPath
importPathString
,
path
string
,
src
[]
byte
,
userRequested
bool
)
error
{
glog
.
V
(
6
)
.
Infof
(
"addFile %s %s"
,
pkgPath
,
path
)
p
,
err
:=
parser
.
ParseFile
(
b
.
fset
,
path
,
src
,
parser
.
DeclarationErrors
|
parser
.
ParseComments
)
if
err
!=
nil
{
return
err
}
dirPath
:=
filepath
.
Dir
(
path
)
if
prev
,
found
:=
b
.
absPaths
[
pkg
];
found
{
if
dirPath
!=
prev
{
return
fmt
.
Errorf
(
"package %q (%s) previously resolved to %s"
,
pkg
,
dirPath
,
prev
)
}
}
else
{
b
.
absPaths
[
pkg
]
=
dirPath
}
b
.
parsed
[
pkg
]
=
append
(
b
.
parsed
[
pkg
],
parsedFile
{
path
,
p
})
b
.
userRequested
[
pkg
]
=
userRequested
// This is redundant with addDir, but some tests call AddFileForTest, which
// call into here without calling addDir.
b
.
userRequested
[
pkgPath
]
=
userRequested
||
b
.
userRequested
[
pkgPath
]
b
.
parsed
[
pkgPath
]
=
append
(
b
.
parsed
[
pkgPath
],
parsedFile
{
path
,
p
})
for
_
,
c
:=
range
p
.
Comments
{
position
:=
b
.
fset
.
Position
(
c
.
End
())
b
.
endLineToCommentGroup
[
fileLine
{
position
.
Filename
,
position
.
Line
}]
=
c
...
...
@@ -177,12 +188,12 @@ func (b *Builder) addFile(pkg string, path string, src []byte, userRequested boo
// We have to get the packages from this specific file, in case the
// user added individual files instead of entire directories.
if
b
.
importGraph
[
pkg
]
==
nil
{
b
.
importGraph
[
pkg
]
=
map
[
string
]
struct
{}{}
if
b
.
importGraph
[
pkg
Path
]
==
nil
{
b
.
importGraph
[
pkg
Path
]
=
map
[
string
]
struct
{}{}
}
for
_
,
im
:=
range
p
.
Imports
{
importedPath
:=
strings
.
Trim
(
im
.
Path
.
Value
,
`"`
)
b
.
importGraph
[
pkg
][
importedPath
]
=
struct
{}{}
b
.
importGraph
[
pkg
Path
][
importedPath
]
=
struct
{}{}
}
return
nil
}
...
...
@@ -191,45 +202,40 @@ func (b *Builder) addFile(pkg string, path string, src []byte, userRequested boo
// a single go package in it. GOPATH, GOROOT, and the location of your go
// binary (`which go`) will all be searched if dir doesn't literally resolve.
func
(
b
*
Builder
)
AddDir
(
dir
string
)
error
{
return
b
.
addDir
(
dir
,
true
)
_
,
err
:=
b
.
importPackage
(
dir
,
true
)
return
err
}
// AddDirRecursive is just like AddDir, but it also recursively adds
// subdirectories; it returns an error only if the path couldn't be resolved;
// any directories recursed into without go source are ignored.
func
(
b
*
Builder
)
AddDirRecursive
(
dir
string
)
error
{
// This is a bit of a hack. The srcDir argument to Import() should
// properly be the dir of the file which depends on the package to be
// imported, so that vendoring can work properly. We assume that there is
// only one level of vendoring, and that the CWD is inside the GOPATH, so
// this should be safe.
cwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"unable to get current directory: %v"
,
err
)
}
// First, find it, so we know what path to use.
pkg
,
err
:=
b
.
context
.
Import
(
dir
,
cwd
,
build
.
FindOnly
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"unable to *find* %q: %v"
,
dir
,
err
)
}
if
err
:=
b
.
addDir
(
dir
,
true
);
err
!=
nil
{
// Add the root.
if
_
,
err
:=
b
.
importPackage
(
dir
,
true
);
err
!=
nil
{
glog
.
Warningf
(
"Ignoring directory %v: %v"
,
dir
,
err
)
}
prefix
:=
strings
.
TrimSuffix
(
pkg
.
Dir
,
strings
.
TrimSuffix
(
dir
,
"/"
))
filepath
.
Walk
(
pkg
.
Dir
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
// filepath.Walk includes the root dir, but we already did that, so we'll
// remove that prefix and rebuild a package import path.
prefix
:=
b
.
buildPackages
[
dir
]
.
Dir
fn
:=
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
if
info
!=
nil
&&
info
.
IsDir
()
{
trimmed
:=
strings
.
TrimPrefix
(
path
,
prefix
)
if
trimmed
!=
""
{
if
err
:=
b
.
addDir
(
trimmed
,
true
);
err
!=
nil
{
glog
.
Warningf
(
"Ignoring child directory %v: %v"
,
trimmed
,
err
)
rel
:=
strings
.
TrimPrefix
(
path
,
prefix
)
if
rel
!=
""
{
// Make a pkg path.
pkg
:=
filepath
.
Join
(
b
.
buildPackages
[
dir
]
.
ImportPath
,
rel
)
// Add it.
if
_
,
err
:=
b
.
importPackage
(
pkg
,
true
);
err
!=
nil
{
glog
.
Warningf
(
"Ignoring child directory %v: %v"
,
pkg
,
err
)
}
}
}
return
nil
})
}
if
err
:=
filepath
.
Walk
(
b
.
buildPackages
[
dir
]
.
Dir
,
fn
);
err
!=
nil
{
return
err
}
return
nil
}
...
...
@@ -239,44 +245,46 @@ func (b *Builder) AddDirRecursive(dir string) error {
// GOPATH, GOROOT, and the location of your go binary (`which go`) will all be
// searched if dir doesn't literally resolve.
func
(
b
*
Builder
)
AddDirTo
(
dir
string
,
u
*
types
.
Universe
)
error
{
if
_
,
found
:=
b
.
parsed
[
dir
];
!
found
{
// We want all types from this package, as if they were directly added
// by the user. They WERE added by the user, in effect.
if
err
:=
b
.
addDir
(
dir
,
true
);
err
!=
nil
{
return
err
}
}
else
{
// We already had this package, but we want it to be considered as if
// the user addid it directly.
b
.
userRequested
[
dir
]
=
true
// We want all types from this package, as if they were directly added
// by the user. They WERE added by the user, in effect.
if
_
,
err
:=
b
.
importPackage
(
dir
,
true
);
err
!=
nil
{
return
err
}
return
b
.
findTypesIn
(
dir
,
u
)
return
b
.
findTypesIn
(
importPathString
(
b
.
buildPackages
[
dir
]
.
ImportPath
)
,
u
)
}
// The implementation of AddDir. A flag indicates whether this directory was
// user-requested or just from following the import graph.
func
(
b
*
Builder
)
addDir
(
dir
string
,
userRequested
bool
)
error
{
pkg
,
err
:=
b
.
buildPackage
(
dir
)
glog
.
V
(
5
)
.
Infof
(
"addDir %s"
,
dir
)
buildPkg
,
err
:=
b
.
importBuildPackage
(
dir
)
if
err
!=
nil
{
return
err
}
// Check in case this package was added (maybe dir was not canonical)
if
wasRequested
,
wasAdded
:=
b
.
userRequested
[
dir
];
wasAdded
{
if
!
userRequested
||
userRequested
==
wasRequested
{
return
nil
pkgPath
:=
importPathString
(
buildPkg
.
ImportPath
)
if
dir
!=
buildPkg
.
ImportPath
{
glog
.
V
(
5
)
.
Infof
(
"addDir %s, canonical path is %s"
,
dir
,
pkgPath
)
}
// Sanity check the pkg dir has not changed.
if
prev
,
found
:=
b
.
absPaths
[
pkgPath
];
found
{
if
buildPkg
.
Dir
!=
prev
{
return
fmt
.
Errorf
(
"package %q (%s) previously resolved to %s"
,
pkgPath
,
buildPkg
.
Dir
,
prev
)
}
}
else
{
b
.
absPaths
[
pkgPath
]
=
buildPkg
.
Dir
}
for
_
,
n
:=
range
p
kg
.
GoFiles
{
for
_
,
n
:=
range
buildP
kg
.
GoFiles
{
if
!
strings
.
HasSuffix
(
n
,
".go"
)
{
continue
}
absPath
:=
filepath
.
Join
(
p
kg
.
Dir
,
n
)
absPath
:=
filepath
.
Join
(
buildP
kg
.
Dir
,
n
)
data
,
err
:=
ioutil
.
ReadFile
(
absPath
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"while loading %q: %v"
,
absPath
,
err
)
}
err
=
b
.
addFile
(
dir
,
absPath
,
data
,
userRequested
)
err
=
b
.
addFile
(
pkgPath
,
absPath
,
data
,
userRequested
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"while parsing %q: %v"
,
absPath
,
err
)
}
...
...
@@ -284,32 +292,53 @@ func (b *Builder) addDir(dir string, userRequested bool) error {
return
nil
}
// importer is a function that will be called by the type check package when it
// needs to import a go package. 'path' is the import path. go1.5 changes the
// interface, and importAdapter below implements the new interface in terms of
// the old one.
func
(
b
*
Builder
)
importer
(
imports
map
[
string
]
*
tc
.
Package
,
path
string
)
(
*
tc
.
Package
,
error
)
{
if
pkg
,
ok
:=
imports
[
path
];
ok
{
return
pkg
,
nil
// importPackage is a function that will be called by the type check package when it
// needs to import a go package. 'path' is the import path.
func
(
b
*
Builder
)
importPackage
(
dir
string
,
userRequested
bool
)
(
*
tc
.
Package
,
error
)
{
glog
.
V
(
5
)
.
Infof
(
"importPackage %s"
,
dir
)
var
pkgPath
=
importPathString
(
dir
)
// Get the canonical path if we can.
if
buildPkg
:=
b
.
buildPackages
[
dir
];
buildPkg
!=
nil
{
glog
.
V
(
5
)
.
Infof
(
"importPackage %s, canonical path is %s"
,
dir
,
buildPkg
.
ImportPath
)
pkgPath
=
importPathString
(
buildPkg
.
ImportPath
)
}
// If we have not seen this before, process it now.
ignoreError
:=
false
if
_
,
ours
:=
b
.
parsed
[
path
];
!
ours
{
if
_
,
found
:=
b
.
parsed
[
pkgPath
];
!
found
{
// Ignore errors in paths that we're importing solely because
// they're referenced by other packages.
ignoreError
=
true
if
err
:=
b
.
addDir
(
path
,
false
);
err
!=
nil
{
// Add it.
if
err
:=
b
.
addDir
(
dir
,
userRequested
);
err
!=
nil
{
return
nil
,
err
}
// Get the canonical path now that it has been added.
if
buildPkg
:=
b
.
buildPackages
[
dir
];
buildPkg
!=
nil
{
glog
.
V
(
5
)
.
Infof
(
"importPackage %s, canonical path is %s"
,
dir
,
buildPkg
.
ImportPath
)
pkgPath
=
importPathString
(
buildPkg
.
ImportPath
)
}
}
pkg
,
err
:=
b
.
typeCheckPackage
(
path
)
// If it was previously known, just check that the user-requestedness hasn't
// changed.
b
.
userRequested
[
pkgPath
]
=
userRequested
||
b
.
userRequested
[
pkgPath
]
// Run the type checker. We may end up doing this to pkgs that are already
// done, or are in the queue to be done later, but it will short-circuit,
// and we can't miss pkgs that are only depended on.
pkg
,
err
:=
b
.
typeCheckPackage
(
pkgPath
)
if
err
!=
nil
{
if
ignoreError
&&
pkg
!=
nil
{
glog
.
V
(
2
)
.
Infof
(
"type checking encountered some errors in %q, but ignoring.
\n
"
,
path
)
glog
.
V
(
2
)
.
Infof
(
"type checking encountered some errors in %q, but ignoring.
\n
"
,
p
kgP
ath
)
}
else
{
return
nil
,
err
}
}
imports
[
path
]
=
pkg
return
pkg
,
nil
}
...
...
@@ -318,85 +347,58 @@ type importAdapter struct {
}
func
(
a
importAdapter
)
Import
(
path
string
)
(
*
tc
.
Package
,
error
)
{
return
a
.
b
.
import
er
(
a
.
b
.
pkgs
,
path
)
return
a
.
b
.
import
Package
(
path
,
false
)
}
// typeCheckPackage will attempt to return the package even if there are some
// errors, so you may check whether the package is nil or not even if you get
// an error.
func
(
b
*
Builder
)
typeCheckPackage
(
id
string
)
(
*
tc
.
Package
,
error
)
{
if
pkg
,
ok
:=
b
.
pkgs
[
id
];
ok
{
func
(
b
*
Builder
)
typeCheckPackage
(
pkgPath
importPathString
)
(
*
tc
.
Package
,
error
)
{
glog
.
V
(
5
)
.
Infof
(
"typeCheckPackage %s"
,
pkgPath
)
if
pkg
,
ok
:=
b
.
typeCheckedPackages
[
pkgPath
];
ok
{
if
pkg
!=
nil
{
glog
.
V
(
6
)
.
Infof
(
"typeCheckPackage %s already done"
,
pkgPath
)
return
pkg
,
nil
}
// We store a nil right before starting work on a package. So
// if we get here and it's present and nil, that means there's
// another invocation of this function on the call stack
// already processing this package.
return
nil
,
fmt
.
Errorf
(
"circular dependency for %q"
,
id
)
return
nil
,
fmt
.
Errorf
(
"circular dependency for %q"
,
pkgPath
)
}
parsedFiles
,
ok
:=
b
.
parsed
[
id
]
parsedFiles
,
ok
:=
b
.
parsed
[
pkgPath
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"No files for pkg %q: %#v"
,
id
,
b
.
parsed
)
return
nil
,
fmt
.
Errorf
(
"No files for pkg %q: %#v"
,
pkgPath
,
b
.
parsed
)
}
files
:=
make
([]
*
ast
.
File
,
len
(
parsedFiles
))
for
i
:=
range
parsedFiles
{
files
[
i
]
=
parsedFiles
[
i
]
.
file
}
b
.
pkgs
[
id
]
=
nil
b
.
typeCheckedPackages
[
pkgPath
]
=
nil
c
:=
tc
.
Config
{
IgnoreFuncBodies
:
true
,
// Note that importAda
ter can call b.import
which calls this
// Note that importAda
pter can call b.importPackage
which calls this
// method. So there can't be cycles in the import graph.
Importer
:
importAdapter
{
b
},
Error
:
func
(
err
error
)
{
glog
.
V
(
2
)
.
Infof
(
"type checker error: %v
\n
"
,
err
)
},
}
pkg
,
err
:=
c
.
Check
(
id
,
b
.
fset
,
files
,
nil
)
b
.
pkgs
[
id
]
=
pkg
// record the result whether or not there was an error
pkg
,
err
:=
c
.
Check
(
string
(
pkgPath
)
,
b
.
fset
,
files
,
nil
)
b
.
typeCheckedPackages
[
pkgPath
]
=
pkg
// record the result whether or not there was an error
return
pkg
,
err
}
func
(
b
*
Builder
)
makeAllPackages
()
error
{
// Take a snapshot to iterate, since this will recursively mutate b.parsed.
keys
:=
[]
string
{}
for
id
:=
range
b
.
parsed
{
keys
=
append
(
keys
,
id
)
}
for
_
,
id
:=
range
keys
{
if
_
,
err
:=
b
.
makePackage
(
id
);
err
!=
nil
{
return
err
}
}
return
nil
}
func
(
b
*
Builder
)
makePackage
(
id
string
)
(
*
tc
.
Package
,
error
)
{
if
b
.
pkgs
==
nil
{
b
.
pkgs
=
map
[
string
]
*
tc
.
Package
{}
}
// We have to check here even though we made a new one above,
// because typeCheckPackage follows the import graph, which may
// cause a package to be filled before we get to it in this
// loop.
if
pkg
,
done
:=
b
.
pkgs
[
id
];
done
{
return
pkg
,
nil
}
return
b
.
typeCheckPackage
(
id
)
}
// FindPackages fetches a list of the user-imported packages.
// Note that you need to call b.FindTypes() first.
func
(
b
*
Builder
)
FindPackages
()
[]
string
{
result
:=
[]
string
{}
for
pkgPath
:=
range
b
.
pkg
s
{
for
pkgPath
:=
range
b
.
typeCheckedPackage
s
{
if
b
.
userRequested
[
pkgPath
]
{
// Since walkType is recursive, all types that are in packages that
// were directly mentioned will be included. We don't need to
// include all types in all transitive packages, though.
result
=
append
(
result
,
pkgPath
)
result
=
append
(
result
,
string
(
pkgPath
)
)
}
}
return
result
...
...
@@ -405,13 +407,15 @@ func (b *Builder) FindPackages() []string {
// FindTypes finalizes the package imports, and searches through all the
// packages for types.
func
(
b
*
Builder
)
FindTypes
()
(
types
.
Universe
,
error
)
{
if
err
:=
b
.
makeAllPackages
();
err
!=
nil
{
return
nil
,
err
}
u
:=
types
.
Universe
{}
// Take a snapshot of pkgs to iterate, since this will recursively mutate
// b.parsed.
keys
:=
[]
importPathString
{}
for
pkgPath
:=
range
b
.
parsed
{
keys
=
append
(
keys
,
pkgPath
)
}
for
_
,
pkgPath
:=
range
keys
{
if
err
:=
b
.
findTypesIn
(
pkgPath
,
&
u
);
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -421,22 +425,28 @@ func (b *Builder) FindTypes() (types.Universe, error) {
// findTypesIn finalizes the package import and searches through the package
// for types.
func
(
b
*
Builder
)
findTypesIn
(
pkgPath
string
,
u
*
types
.
Universe
)
error
{
pkg
,
err
:=
b
.
makePackage
(
pkgPath
)
if
err
!=
nil
{
return
err
func
(
b
*
Builder
)
findTypesIn
(
pkgPath
importPathString
,
u
*
types
.
Universe
)
error
{
glog
.
V
(
5
)
.
Infof
(
"findTypesIn %s"
,
pkgPath
)
pkg
:=
b
.
typeCheckedPackages
[
pkgPath
]
if
pkg
==
nil
{
return
fmt
.
Errorf
(
"findTypesIn(%s): package is not known"
,
pkgPath
)
}
if
!
b
.
userRequested
[
pkgPath
]
{
// Since walkType is recursive, all types that the
// packages they asked for depend on will be included.
// But we don't need to include all types in all
// *packages* they depend on.
glog
.
V
(
5
)
.
Infof
(
"findTypesIn %s: package is not user requested"
,
pkgPath
)
return
nil
}
// We're keeping this package. This call will create the record.
u
.
Package
(
string
(
pkgPath
))
.
Name
=
pkg
.
Name
()
u
.
Package
(
string
(
pkgPath
))
.
Path
=
pkg
.
Path
()
for
_
,
f
:=
range
b
.
parsed
[
pkgPath
]
{
if
strings
.
HasSuffix
(
f
.
name
,
"/doc.go"
)
{
tp
:=
u
.
Package
(
pkgPath
)
tp
:=
u
.
Package
(
string
(
pkgPath
)
)
for
i
:=
range
f
.
file
.
Comments
{
tp
.
Comments
=
append
(
tp
.
Comments
,
splitLines
(
f
.
file
.
Comments
[
i
]
.
Text
())
...
)
}
...
...
@@ -480,12 +490,30 @@ func (b *Builder) findTypesIn(pkgPath string, u *types.Universe) error {
}
}
for
p
:=
range
b
.
importGraph
[
pkgPath
]
{
u
.
AddImports
(
pkgPath
,
p
)
u
.
AddImports
(
string
(
pkgPath
)
,
p
)
}
u
.
Package
(
pkgPath
)
.
Name
=
pkg
.
Name
()
return
nil
}
func
(
b
*
Builder
)
importWithMode
(
dir
string
,
mode
build
.
ImportMode
)
(
*
build
.
Package
,
error
)
{
// This is a bit of a hack. The srcDir argument to Import() should
// properly be the dir of the file which depends on the package to be
// imported, so that vendoring can work properly and local paths can
// resolve. We assume that there is only one level of vendoring, and that
// the CWD is inside the GOPATH, so this should be safe. Nobody should be
// using local (relative) paths except on the CLI, so CWD is also
// sufficient.
cwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"unable to get current directory: %v"
,
err
)
}
buildPkg
,
err
:=
b
.
context
.
Import
(
dir
,
cwd
,
mode
)
if
err
!=
nil
{
return
nil
,
err
}
return
buildPkg
,
nil
}
// if there's a comment on the line `lines` before pos, return its text, otherwise "".
func
(
b
*
Builder
)
priorCommentLines
(
pos
token
.
Pos
,
lines
int
)
*
ast
.
CommentGroup
{
position
:=
b
.
fset
.
Position
(
pos
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment