cgo: add file AST for fake C file locations
This is needed for the type checker, otherwise it doesn't know which Go version it should use for type checking.
Этот коммит содержится в:
родитель
0ad15551c8
коммит
53db436a7d
5 изменённых файлов: 38 добавлений и 6 удалений
12
cgo/cgo.go
12
cgo/cgo.go
|
@ -25,9 +25,15 @@ import (
|
||||||
"golang.org/x/tools/go/ast/astutil"
|
"golang.org/x/tools/go/ast/astutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Function that's only defined in Go 1.22.
|
||||||
|
var setASTFileFields = func(f *ast.File, start, end token.Pos) {
|
||||||
|
}
|
||||||
|
|
||||||
// cgoPackage holds all CGo-related information of a package.
|
// cgoPackage holds all CGo-related information of a package.
|
||||||
type cgoPackage struct {
|
type cgoPackage struct {
|
||||||
generated *ast.File
|
generated *ast.File
|
||||||
|
packageName string
|
||||||
|
cgoFiles []*ast.File
|
||||||
generatedPos token.Pos
|
generatedPos token.Pos
|
||||||
errors []error
|
errors []error
|
||||||
currentDir string // current working directory
|
currentDir string // current working directory
|
||||||
|
@ -165,8 +171,9 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
||||||
// hashes of the accessed C header files. If there is one or more error, it
|
// hashes of the accessed C header files. If there is one or more error, it
|
||||||
// returns these in the []error slice but still modifies the AST.
|
// returns these in the []error slice but still modifies the AST.
|
||||||
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string) ([]*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||||
p := &cgoPackage{
|
p := &cgoPackage{
|
||||||
|
packageName: files[0].Name.Name,
|
||||||
currentDir: dir,
|
currentDir: dir,
|
||||||
importPath: importPath,
|
importPath: importPath,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
|
@ -202,6 +209,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||||
// This is always a bug in the cgo package.
|
// This is always a bug in the cgo package.
|
||||||
panic("unexpected error: " + err.Error())
|
panic("unexpected error: " + err.Error())
|
||||||
}
|
}
|
||||||
|
p.cgoFiles = append(p.cgoFiles, p.generated)
|
||||||
// If the Comments field is not set to nil, the go/format package will get
|
// If the Comments field is not set to nil, the go/format package will get
|
||||||
// confused about where comments should go.
|
// confused about where comments should go.
|
||||||
p.generated.Comments = nil
|
p.generated.Comments = nil
|
||||||
|
@ -332,7 +340,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||||
// Print the newly generated in-memory AST, for debugging.
|
// Print the newly generated in-memory AST, for debugging.
|
||||||
//ast.Print(fset, p.generated)
|
//ast.Print(fset, p.generated)
|
||||||
|
|
||||||
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
return p.cgoFiles, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
||||||
|
|
17
cgo/cgo_go122.go
Обычный файл
17
cgo/cgo_go122.go
Обычный файл
|
@ -0,0 +1,17 @@
|
||||||
|
//go:build go1.22
|
||||||
|
|
||||||
|
package cgo
|
||||||
|
|
||||||
|
// Code specifically for Go 1.22.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setASTFileFields = func(f *ast.File, start, end token.Pos) {
|
||||||
|
f.FileStart = start
|
||||||
|
f.FileEnd = end
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ func TestCGo(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the AST with CGo.
|
// Process the AST with CGo.
|
||||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags)
|
cgoFiles, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags)
|
||||||
|
|
||||||
// Check the AST for type errors.
|
// Check the AST for type errors.
|
||||||
var typecheckErrors []error
|
var typecheckErrors []error
|
||||||
|
@ -66,7 +66,7 @@ func TestCGo(t *testing.T) {
|
||||||
Importer: simpleImporter{},
|
Importer: simpleImporter{},
|
||||||
Sizes: types.SizesFor("gccgo", "arm"),
|
Sizes: types.SizesFor("gccgo", "arm"),
|
||||||
}
|
}
|
||||||
_, err = config.Check("", fset, []*ast.File{f, cgoAST}, nil)
|
_, err = config.Check("", fset, append([]*ast.File{f}, cgoFiles...), nil)
|
||||||
if err != nil && len(typecheckErrors) == 0 {
|
if err != nil && len(typecheckErrors) == 0 {
|
||||||
// Only report errors when no type errors are found (an
|
// Only report errors when no type errors are found (an
|
||||||
// unexpected condition).
|
// unexpected condition).
|
||||||
|
@ -91,7 +91,7 @@ func TestCGo(t *testing.T) {
|
||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
err = format.Node(buf, fset, cgoAST)
|
err = format.Node(buf, fset, cgoFiles[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("could not write out CGo AST: %v", err)
|
t.Errorf("could not write out CGo AST: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,6 +589,13 @@ func (p *cgoPackage) getClangLocationPosition(location C.CXSourceLocation, tu C.
|
||||||
f := p.fset.AddFile(filename, -1, int(size))
|
f := p.fset.AddFile(filename, -1, int(size))
|
||||||
f.SetLines(lines)
|
f.SetLines(lines)
|
||||||
p.tokenFiles[filename] = f
|
p.tokenFiles[filename] = f
|
||||||
|
// Add dummy file AST, to satisfy the type checker.
|
||||||
|
astFile := &ast.File{
|
||||||
|
Package: f.Pos(0),
|
||||||
|
Name: ast.NewIdent(p.packageName),
|
||||||
|
}
|
||||||
|
setASTFileFields(astFile, f.Pos(0), f.Pos(int(size)))
|
||||||
|
p.cgoFiles = append(p.cgoFiles, astFile)
|
||||||
}
|
}
|
||||||
positionFile := p.tokenFiles[filename]
|
positionFile := p.tokenFiles[filename]
|
||||||
|
|
||||||
|
|
|
@ -447,7 +447,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
fileErrs = append(fileErrs, errs...)
|
fileErrs = append(fileErrs, errs...)
|
||||||
}
|
}
|
||||||
files = append(files, generated)
|
files = append(files, generated...)
|
||||||
p.program.LDFlags = append(p.program.LDFlags, ldflags...)
|
p.program.LDFlags = append(p.program.LDFlags, ldflags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче