//ParsePackage parses package and filling info structure. //It's filling info about all internal packages even if they //are not imported in the root package. func ParsePackage(pkgName string, info *types.Info) (*types.Package, *token.FileSet, error) { collectImporter := new(importer.CollectInfoImporter) collectImporter.Info = info var resultPkg *types.Package var resultFset *token.FileSet parsedPackages := make(map[string]bool) notParsedPackage := pkgName for len(notParsedPackage) > 0 { collectImporter.Pkg = notParsedPackage pkg, fset, err := collectImporter.Collect() if err != nil { return nil, nil, err } //Filling results only from first package //that was passed as argument to function if resultPkg == nil { resultPkg = pkg resultFset = fset } parsedPackages[notParsedPackage] = true //Searching for a new package that was not parsed before notParsedPackage = "" files, err := fs.GetUnusedSources(pkgName, fset) if err != nil { return nil, nil, err } for _, f := range files { newNotParsedPackage := fs.GetPackagePath(f) if !parsedPackages[newNotParsedPackage] { notParsedPackage = newNotParsedPackage break } else { util.Info("package %s has been already parsed, however %s file is still unused", newNotParsedPackage, f) } } } return resultPkg, resultFset, nil }
func isUsed(def *Definition) bool { used := true if len(def.Usages) == 0 { used = false } else { //Checking pathes of usages to not count internal hasExternalUsages := false util.Debug("checking [%s]", def.Name) for _, u := range def.Usages { pkgPath := "" if def.Pkg != nil { pkgPath = def.Pkg.Path() } else if dotIdx := strings.LastIndex(def.Name, "."); dotIdx >= 0 { pkgPath = def.Name[0:dotIdx] } util.Debug("checking [%v]", u.Pos) if u.Pos.IsValid() && fs.GetPackagePath(u.Pos.Filename) != pkgPath { hasExternalUsages = true break } } used = hasExternalUsages } if !used { //Check all interfaces for _, i := range def.Interfaces { if isUsed(i) { used = true break } } } return used }