Process extracts `import "C"` statements from the AST, parses the comment with libclang, and modifies the AST to use this information. It returns a newly created *ast.File that should be added to the list of to-be-parsed files, the CGo header snippets that should be compiled (for inline functions),
(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, goos string)
| 255 | // hashes of the accessed C header files. If there is one or more error, it |
| 256 | // returns these in the []error slice but still modifies the AST. |
| 257 | func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, goos string) ([]*ast.File, []string, []string, []string, map[string][]byte, []error) { |
| 258 | p := &cgoPackage{ |
| 259 | packageName: files[0].Name.Name, |
| 260 | currentDir: dir, |
| 261 | importPath: importPath, |
| 262 | fset: fset, |
| 263 | tokenFiles: map[string]*token.File{}, |
| 264 | definedGlobally: map[string]ast.Node{}, |
| 265 | noescapingFuncs: map[string]*noescapingFunc{}, |
| 266 | anonDecls: map[interface{}]string{}, |
| 267 | visitedFiles: map[string][]byte{}, |
| 268 | } |
| 269 | |
| 270 | // Add a new location for the following file. |
| 271 | generatedTokenPos := p.fset.AddFile(dir+"/!cgo.go", -1, 0) |
| 272 | generatedTokenPos.SetLines([]int{0}) |
| 273 | p.generatedPos = generatedTokenPos.Pos(0) |
| 274 | |
| 275 | // Find the absolute path for this package. |
| 276 | packagePath, err := filepath.Abs(fset.File(files[0].Pos()).Name()) |
| 277 | if err != nil { |
| 278 | return nil, nil, nil, nil, nil, []error{ |
| 279 | scanner.Error{ |
| 280 | Pos: fset.Position(files[0].Pos()), |
| 281 | Msg: "cgo: cannot find absolute path: " + err.Error(), // TODO: wrap this error |
| 282 | }, |
| 283 | } |
| 284 | } |
| 285 | p.packageDir = filepath.Dir(packagePath) |
| 286 | |
| 287 | // Construct a new in-memory AST for CGo declarations of this package. |
| 288 | // The first part is written as Go code that is then parsed, but more code |
| 289 | // is added later to the AST to declare functions, globals, etc. |
| 290 | goCode := "package " + files[0].Name.Name + "\n\n" |
| 291 | if goos == "windows" { |
| 292 | goCode += generatedGoFilePrefixWindows |
| 293 | } else { |
| 294 | goCode += generatedGoFilePrefixOther |
| 295 | } |
| 296 | p.generated, err = parser.ParseFile(fset, dir+"/!cgo.go", goCode, parser.ParseComments) |
| 297 | if err != nil { |
| 298 | // This is always a bug in the cgo package. |
| 299 | panic("unexpected error: " + err.Error()) |
| 300 | } |
| 301 | p.cgoFiles = append(p.cgoFiles, p.generated) |
| 302 | // If the Comments field is not set to nil, the go/format package will get |
| 303 | // confused about where comments should go. |
| 304 | p.generated.Comments = nil |
| 305 | |
| 306 | // Find `import "C"` C fragments in the file. |
| 307 | p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file |
| 308 | for i, f := range files { |
| 309 | var cgoHeader string |
| 310 | for i := 0; i < len(f.Decls); i++ { |
| 311 | decl := f.Decls[i] |
| 312 | genDecl, ok := decl.(*ast.GenDecl) |
| 313 | if !ok { |
| 314 | continue |