diff --git a/build/build.go b/build/build.go index 9de1257f..14b5cdb9 100644 --- a/build/build.go +++ b/build/build.go @@ -1,6 +1,7 @@ package build import ( + "encoding/json" "fmt" "go/ast" "go/build" @@ -498,8 +499,10 @@ type Options struct { MapToLocalDisk bool Minify bool Color bool - BuildTags []string Rebuild bool + Analyze bool + AnalyzeJson bool + BuildTags []string } func (o *Options) PrintError(format string, a ...interface{}) { @@ -965,7 +968,7 @@ func (s *Session) WriteCommandPackage(archive *compiler.Archive, pkgObj string) defer func() { m.WriteTo(mapFile) mapFile.Close() - fmt.Fprintf(codeFile, "//# sourceMappingURL=%s.map\n", filepath.Base(pkgObj)) + fmt.Fprintf(sourceMapFilter.Writer, "//# sourceMappingURL=%s.map\n", filepath.Base(pkgObj)) }() sourceMapFilter.MappingCallback = NewMappingCallback(m, s.options.GOROOT, s.options.GOPATH, s.options.MapToLocalDisk) @@ -981,7 +984,27 @@ func (s *Session) WriteCommandPackage(archive *compiler.Archive, pkgObj string) if err != nil { return err } - return compiler.WriteProgramCode(deps, sourceMapFilter) + infos, err := compiler.WriteProgramCode(deps, sourceMapFilter) + if s.options.Analyze { + if s.options.AnalyzeJson { + data, _ := json.MarshalIndent(&infos, "", "\t") + fmt.Println(string(data)) + } else { + var maxSize int64 + for _, info := range infos { + if info.Size > maxSize { + maxSize = info.Size + } + } + noff := len(strconv.FormatInt(maxSize, 10)) + format := fmt.Sprintf("%%%vv\t%%v\n", noff) + fmt.Printf(format, "", "") + for _, info := range infos { + fmt.Printf(format, info.Size, info.ImportPath) + } + } + } + return err } func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool) func(generatedLine, generatedColumn int, originalPos token.Position) { diff --git a/compiler/compiler.go b/compiler/compiler.go index 890d26f2..1e94c2ef 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -102,7 +102,7 @@ type dceInfo struct { methodFilter string } -func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) error { +func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) ([]*PkgInfo, error) { mainPkg := pkgs[len(pkgs)-1] minify := mainPkg.Minified @@ -152,31 +152,52 @@ func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) error { } if _, err := w.Write([]byte("\"use strict\";\n(function() {\n\n")); err != nil { - return err + return nil, err } preludeJS := prelude.Prelude if minify { preludeJS = prelude.Minified } if _, err := io.WriteString(w, preludeJS); err != nil { - return err + return nil, err } if _, err := w.Write([]byte("\n")); err != nil { - return err + return nil, err } // write packages + offset := w.offset + + var infos []*PkgInfo + infos = append(infos, &PkgInfo{ + Name: "$prelude", + ImportPath: "$prelude", + Size: w.offset, + }) for _, pkg := range pkgs { if err := WritePkgCode(pkg, dceSelection, minify, w); err != nil { - return err + return nil, err } + infos = append(infos, &PkgInfo{ + Name: pkg.Name, + ImportPath: pkg.ImportPath, + Imports: pkg.Imports, + Size: w.offset - offset, + }) + offset = w.offset } if _, err := w.Write([]byte("$synthesizeMethods();\nvar $mainPkg = $packages[\"" + string(mainPkg.ImportPath) + "\"];\n$packages[\"runtime\"].$init();\n$go($mainPkg.$init, []);\n$flushConsole();\n\n}).call(this);\n")); err != nil { - return err + return nil, err } + return infos, nil +} - return nil +type PkgInfo struct { + Name string `json:"Name"` + ImportPath string `json:"ImportPath,omitempty"` + Imports []string `json:"Imports,omitempty"` + Size int64 `json:"Size"` } func WritePkgCode(pkg *Archive, dceSelection map[*Decl]struct{}, minify bool, w *SourceMapFilter) error { @@ -260,9 +281,14 @@ type SourceMapFilter struct { MappingCallback func(generatedLine, generatedColumn int, originalPos token.Position) line int column int + offset int64 fileSet *token.FileSet } +func (f *SourceMapFilter) Offset() int64 { + return f.offset +} + func (f *SourceMapFilter) Write(p []byte) (n int, err error) { var n2 int for { @@ -274,6 +300,7 @@ func (f *SourceMapFilter) Write(p []byte) (n int, err error) { n2, err = f.Writer.Write(w) n += n2 + f.offset += int64(n2) for { i := bytes.IndexByte(w, '\n') if i == -1 { diff --git a/tool.go b/tool.go index 1bc6ef57..3fb17edf 100644 --- a/tool.go +++ b/tool.go @@ -82,6 +82,8 @@ func main() { compilerFlags.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build") compilerFlags.BoolVar(&options.MapToLocalDisk, "localmap", false, "use local paths for sourcemap") compilerFlags.BoolVarP(&options.Rebuild, "force", "a", false, "force rebuilding of packages that are already up-to-date") + compilerFlags.BoolVar(&options.Analyze, "analyze", false, "print analyze build package's info") + compilerFlags.BoolVar(&options.AnalyzeJson, "json", false, "print analyze build package's json info") flagWatch := pflag.NewFlagSet("", 0) flagWatch.BoolVarP(&options.Watch, "watch", "w", false, "watch for changes to the source files") @@ -590,7 +592,7 @@ func (fs serveCommandFileSystem) Open(requestName string) (http.File, error) { if err != nil { return err } - if err := compiler.WriteProgramCode(deps, sourceMapFilter); err != nil { + if _, err = compiler.WriteProgramCode(deps, sourceMapFilter); err != nil { return err }