func doParseFiles(filePathes []string, fset *token.FileSet) (*token.FileSet, []*ast.File, error) { if fset == nil { fset = token.NewFileSet() } util.Info("parsing files %v", filePathes) astFiles := make([]*ast.File, 0, len(filePathes)) for _, f := range filePathes { //XXX: Ignoring files with packages ends with _test. //XXX: Doing that because getting error in check() //XXX: cause source file is still going to current //XXX: packages. Need to analyze package before //XXX: and check both packages separately. tempFset := token.NewFileSet() astFile, err := parser.ParseFile(tempFset, f, nil, 0) if !strings.HasSuffix(astFile.Name.Name, "_test") { if err != nil { return nil, nil, err } astFile, _ := parser.ParseFile(fset, f, nil, 0) astFiles = append(astFiles, astFile) } } iterateFunc := func(f *token.File) bool { util.Debug("\t%s", f.Name()) return true } fset.Iterate(iterateFunc) return fset, astFiles, nil }
// findQueryPos searches fset for filename and translates the // specified file-relative byte offsets into token.Pos form. It // returns an error if the file was not found or the offsets were out // of bounds. // func findQueryPos(fset *token.FileSet, filename string, startOffset, endOffset int) (start, end token.Pos, err error) { var file *token.File fset.Iterate(func(f *token.File) bool { if sameFile(filename, f.Name()) { // (f.Name() is absolute) file = f return false // done } return true // continue }) if file == nil { err = fmt.Errorf("couldn't find file containing position") return } // Range check [start..end], inclusive of both end-points. if 0 <= startOffset && startOffset <= file.Size() { start = file.Pos(int(startOffset)) } else { err = fmt.Errorf("start position is beyond end of file") return } if 0 <= endOffset && endOffset <= file.Size() { end = file.Pos(int(endOffset)) } else { err = fmt.Errorf("end position is beyond end of file") return } return }
// parseQueryPos parses a string of the form "file:pos" or // file:start,end" where pos, start, end match #%d and represent byte // offsets, and returns the extent to which it refers. // // (Numbers without a '#' prefix are reserved for future use, // e.g. to indicate line/column positions.) // func parseQueryPos(fset *token.FileSet, queryPos string) (start, end token.Pos, err error) { if queryPos == "" { err = fmt.Errorf("no source position specified (-pos flag)") return } colon := strings.LastIndex(queryPos, ":") if colon < 0 { err = fmt.Errorf("invalid source position -pos=%q", queryPos) return } filename, offset := queryPos[:colon], queryPos[colon+1:] startOffset := -1 endOffset := -1 if hyphen := strings.Index(offset, ","); hyphen < 0 { // e.g. "foo.go:#123" startOffset = parseOctothorpDecimal(offset) endOffset = startOffset } else { // e.g. "foo.go:#123,#456" startOffset = parseOctothorpDecimal(offset[:hyphen]) endOffset = parseOctothorpDecimal(offset[hyphen+1:]) } if startOffset < 0 || endOffset < 0 { err = fmt.Errorf("invalid -pos offset %q", offset) return } var file *token.File fset.Iterate(func(f *token.File) bool { if sameFile(filename, f.Name()) { // (f.Name() is absolute) file = f return false // done } return true // continue }) if file == nil { err = fmt.Errorf("couldn't find file containing position -pos=%q", queryPos) return } // Range check [start..end], inclusive of both end-points. if 0 <= startOffset && startOffset <= file.Size() { start = file.Pos(int(startOffset)) } else { err = fmt.Errorf("start position is beyond end of file -pos=%q", queryPos) return } if 0 <= endOffset && endOffset <= file.Size() { end = file.Pos(int(endOffset)) } else { err = fmt.Errorf("end position is beyond end of file -pos=%q", queryPos) return } return }
func LogFileSet(fset *token.FileSet) { Log("FileSet:") fset.Iterate(func(f *token.File) bool { Log(" %s", f.Name()) return true }) }
// getFile assumes that each filename occurs at most once func getFile(fset *token.FileSet, filename string) (file *token.File) { fset.Iterate(func(f *token.File) bool { if f.Name() == filename { if file != nil { panic(filename + " used multiple times") } file = f } return true }) return file }
//GetUnusedSources returns list of source files in package that //are not presenting in the file set func GetUnusedSources(pkg string, fset *token.FileSet) ([]string, error) { unusedSource, err := SourceFiles(pkg, true) if err != nil { return nil, err } iterateFiles := func(f *token.File) bool { idx := indexOf(unusedSource, f.Name()) if idx >= 0 { unusedSource = append(unusedSource[:idx], unusedSource[idx+1:]...) } return true } fset.Iterate(iterateFiles) return unusedSource, nil }
func benchmark(fset *token.FileSet, files []*ast.File, full bool) { b := testing.Benchmark(func(b *testing.B) { for i := 0; i < b.N; i++ { conf := Config{IgnoreFuncBodies: !full} conf.Check("go/types", fset, files, nil) } }) // determine line count lineCount := 0 fset.Iterate(func(f *token.File) bool { lineCount += f.LineCount() return true }) d := time.Duration(b.NsPerOp()) fmt.Printf( "%s/op, %d lines/s, %d KB/op (%d iterations)\n", d, int64(float64(lineCount)/d.Seconds()), b.AllocedBytesPerOp()>>10, b.N, ) }