@@ -412,6 +412,9 @@ type PackageError struct {
412
412
}
413
413
414
414
func (p * PackageError ) Error () string {
415
+ // TODO(#43696): decide when to print the stack or the position based on
416
+ // the error type and whether the package is in the main module.
417
+ // Document the rationale.
415
418
if p .Pos != "" && (len (p .ImportStack ) == 0 || ! p .alwaysPrintStack ) {
416
419
// Omit import stack. The full path to the file where the error
417
420
// is the most important thing.
@@ -1663,11 +1666,6 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
1663
1666
p .setLoadPackageDataError (err , path , stk , importPos )
1664
1667
}
1665
1668
1666
- p .EmbedFiles , p .Internal .Embed , err = p .resolveEmbed (p .EmbedPatterns )
1667
- if err != nil {
1668
- setError (err )
1669
- }
1670
-
1671
1669
useBindir := p .Name == "main"
1672
1670
if ! p .Standard {
1673
1671
switch cfg .BuildBuildmode {
@@ -1803,9 +1801,19 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
1803
1801
return
1804
1802
}
1805
1803
1804
+ // Errors after this point are caused by this package, not the importing
1805
+ // package. Pushing the path here prevents us from reporting the error
1806
+ // with the position of the import declaration.
1806
1807
stk .Push (path )
1807
1808
defer stk .Pop ()
1808
1809
1810
+ p .EmbedFiles , p .Internal .Embed , err = p .resolveEmbed (p .EmbedPatterns )
1811
+ if err != nil {
1812
+ setError (err )
1813
+ embedErr := err .(* EmbedError )
1814
+ p .Error .setPos (p .Internal .Build .EmbedPatternPos [embedErr .Pattern ])
1815
+ }
1816
+
1809
1817
// Check for case-insensitive collision of input files.
1810
1818
// To avoid problems on case-insensitive files, we reject any package
1811
1819
// where two different input files have equal names under a case-insensitive
@@ -1909,6 +1917,20 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
1909
1917
}
1910
1918
}
1911
1919
1920
+ // An EmbedError indicates a problem with a go:embed directive.
1921
+ type EmbedError struct {
1922
+ Pattern string
1923
+ Err error
1924
+ }
1925
+
1926
+ func (e * EmbedError ) Error () string {
1927
+ return fmt .Sprintf ("pattern %s: %v" , e .Pattern , e .Err )
1928
+ }
1929
+
1930
+ func (e * EmbedError ) Unwrap () error {
1931
+ return e .Err
1932
+ }
1933
+
1912
1934
// ResolveEmbed resolves //go:embed patterns and returns only the file list.
1913
1935
// For use by go list to compute p.TestEmbedFiles and p.XTestEmbedFiles.
1914
1936
func (p * Package ) ResolveEmbed (patterns []string ) []string {
@@ -1920,24 +1942,33 @@ func (p *Package) ResolveEmbed(patterns []string) []string {
1920
1942
// It sets files to the list of unique files matched (for go list),
1921
1943
// and it sets pmap to the more precise mapping from
1922
1944
// patterns to files.
1923
- // TODO(rsc): All these messages need position information for better error reports.
1924
1945
func (p * Package ) resolveEmbed (patterns []string ) (files []string , pmap map [string ][]string , err error ) {
1946
+ var pattern string
1947
+ defer func () {
1948
+ if err != nil {
1949
+ err = & EmbedError {
1950
+ Pattern : pattern ,
1951
+ Err : err ,
1952
+ }
1953
+ }
1954
+ }()
1955
+
1925
1956
pmap = make (map [string ][]string )
1926
1957
have := make (map [string ]int )
1927
1958
dirOK := make (map [string ]bool )
1928
1959
pid := 0 // pattern ID, to allow reuse of have map
1929
- for _ , pattern : = range patterns {
1960
+ for _ , pattern = range patterns {
1930
1961
pid ++
1931
1962
1932
1963
// Check pattern is valid for //go:embed.
1933
1964
if _ , err := path .Match (pattern , "" ); err != nil || ! validEmbedPattern (pattern ) {
1934
- return nil , nil , fmt .Errorf ("pattern %s: invalid pattern syntax" , pattern )
1965
+ return nil , nil , fmt .Errorf ("invalid pattern syntax" )
1935
1966
}
1936
1967
1937
1968
// Glob to find matches.
1938
1969
match , err := fsys .Glob (p .Dir + string (filepath .Separator ) + filepath .FromSlash (pattern ))
1939
1970
if err != nil {
1940
- return nil , nil , fmt . Errorf ( "pattern %s: %v" , pattern , err )
1971
+ return nil , nil , err
1941
1972
}
1942
1973
1943
1974
// Filter list of matches down to the ones that will still exist when
@@ -1961,26 +1992,26 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
1961
1992
// (do not contain a go.mod).
1962
1993
for dir := file ; len (dir ) > len (p .Dir )+ 1 && ! dirOK [dir ]; dir = filepath .Dir (dir ) {
1963
1994
if _ , err := fsys .Stat (filepath .Join (dir , "go.mod" )); err == nil {
1964
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed %s %s: in different module" , pattern , what , rel )
1995
+ return nil , nil , fmt .Errorf ("cannot embed %s %s: in different module" , what , rel )
1965
1996
}
1966
1997
if dir != file {
1967
1998
if info , err := fsys .Lstat (dir ); err == nil && ! info .IsDir () {
1968
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed %s %s: in non-directory %s" , pattern , what , rel , dir [len (p .Dir )+ 1 :])
1999
+ return nil , nil , fmt .Errorf ("cannot embed %s %s: in non-directory %s" , what , rel , dir [len (p .Dir )+ 1 :])
1969
2000
}
1970
2001
}
1971
2002
dirOK [dir ] = true
1972
2003
if elem := filepath .Base (dir ); isBadEmbedName (elem ) {
1973
2004
if dir == file {
1974
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed %s %s: invalid name %s" , pattern , what , rel , elem )
2005
+ return nil , nil , fmt .Errorf ("cannot embed %s %s: invalid name %s" , what , rel , elem )
1975
2006
} else {
1976
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed %s %s: in invalid directory %s" , pattern , what , rel , elem )
2007
+ return nil , nil , fmt .Errorf ("cannot embed %s %s: in invalid directory %s" , what , rel , elem )
1977
2008
}
1978
2009
}
1979
2010
}
1980
2011
1981
2012
switch {
1982
2013
default :
1983
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed irregular file %s" , pattern , rel )
2014
+ return nil , nil , fmt .Errorf ("cannot embed irregular file %s" , rel )
1984
2015
1985
2016
case info .Mode ().IsRegular ():
1986
2017
if have [rel ] != pid {
@@ -2027,13 +2058,13 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
2027
2058
return nil , nil , err
2028
2059
}
2029
2060
if count == 0 {
2030
- return nil , nil , fmt .Errorf ("pattern %s: cannot embed directory %s: contains no embeddable files" , pattern , rel )
2061
+ return nil , nil , fmt .Errorf ("cannot embed directory %s: contains no embeddable files" , rel )
2031
2062
}
2032
2063
}
2033
2064
}
2034
2065
2035
2066
if len (list ) == 0 {
2036
- return nil , nil , fmt .Errorf ("pattern %s: no matching files found" , pattern )
2067
+ return nil , nil , fmt .Errorf ("no matching files found" )
2037
2068
}
2038
2069
sort .Strings (list )
2039
2070
pmap [pattern ] = list
0 commit comments