Index: mojom/mojom_parser/generators/deps/deps_generator.go |
diff --git a/mojom/mojom_parser/generators/deps/deps_generator.go b/mojom/mojom_parser/generators/deps/deps_generator.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ee13a3e00fb69218a7b526fa97ce56ea58b2936d |
--- /dev/null |
+++ b/mojom/mojom_parser/generators/deps/deps_generator.go |
@@ -0,0 +1,107 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package main |
+ |
+// deps_generator.go implements the main function of the deps generator. |
+// The deps generator generates .d files. The syntax is that which is used to |
+// specify dependencies in makefiles. |
rudominer
2016/02/27 01:28:10
Can you give a link to something that defines a .d
azani
2016/02/29 21:28:32
Sorry, not really. The format seems to be indirect
|
+ |
+import ( |
+ "log" |
+ "os" |
+ "path" |
+ "path/filepath" |
+ |
+ "mojom/mojom_parser/generators/common" |
+) |
+ |
+func main() { |
+ config := common.GetCliConfig(os.Args) |
+ common.GenerateOutput(WriteDepsFile, GetOutputFile, config) |
+} |
+ |
+// WriteDepsFile writes a .d file for the specified file to the specified writer. |
+func WriteDepsFile(fileName string, config common.GeneratorConfig, writer common.Writer) { |
+ dFileName := fileName[:len(fileName)-len(filepath.Ext(fileName))] + ".d" |
+ writer.WriteString(path.Base(dFileName)) |
+ writer.WriteString(" : ") |
+ |
+ imports := GetTransitiveClosure(fileName, config) |
+ for _, imported := range imports { |
+ writer.WriteString(imported) |
+ writer.WriteString(" ") |
+ } |
+ writer.WriteString("\n") |
+} |
+ |
+// GetOutputFile returns a writer to which the generator output should be |
+// written for that specified file. |
+// In this case, the writer writes to a file whose relative path from |
+// config.OutputDir() if equivalent to the relative path from config.SrcRootPath() |
+// to fileName. |
+// |
+// e.g. If |
+// fileName = /alpha/beta/gamma/file.mojom |
+// SrcRootPath = /alpha/ |
+// OutputDir = /some/output/path/ |
+// |
+// The writer writes to /some/output/path/beta/gamma/file.d |
+// |
+// TODO(azani): This is likely to be a common pattern to for the output path of |
+// the generated code. Refactor into something re-usable before writing the next |
+// generator. |
+func GetOutputFile(fileName string, config common.GeneratorConfig) (file common.Writer) { |
rudominer
2016/02/27 01:28:10
Seems like this or something like it should go in
azani
2016/02/29 21:28:32
Done.
|
+ // Switch the file's extension to .d |
+ fileName = fileName[:len(fileName)-len(filepath.Ext(fileName))] + ".d" |
+ |
+ var err error |
+ relFileName, err := filepath.Rel(config.SrcRootPath(), fileName) |
+ if err != nil { |
+ log.Fatalln(err.Error()) |
+ } |
+ outPath := filepath.Join(config.OutputDir(), relFileName) |
+ |
+ // Create the directory that will contain the output. |
+ outDir := path.Dir(outPath) |
+ if err := os.MkdirAll(outDir, os.ModeDir|0770); err != nil && !os.IsExist(err) { |
+ log.Fatalln(err.Error()) |
+ } |
+ |
+ file, err = os.OpenFile(outPath, os.O_WRONLY, 0660) |
+ if err != nil { |
+ log.Fatalln(err.Error()) |
+ } |
+ |
+ return |
+} |
+ |
+// GetTransitiveClosure gets the list of transitive imports starting with |
+// rootFile. rootFile itself is not included. |
+// The imports are specified as paths relative to the directory in which |
+// rootFile is found. |
+func GetTransitiveClosure(rootFile string, config common.GeneratorConfig) (result []string) { |
rudominer
2016/02/27 01:28:10
Should this also be a common utility?
azani
2016/02/29 21:28:32
Looking at the other current generators, I don't t
|
+ fileGraph := config.FileGraph() |
+ toVisit := []string{rootFile} |
+ rootFileDir := path.Dir(rootFile) |
+ |
+ for len(toVisit) > 0 { |
+ curFileName := toVisit[len(toVisit)-1] |
+ toVisit = toVisit[1:len(toVisit)] |
+ |
+ curFile := fileGraph.Files[curFileName] |
+ rel, err := filepath.Rel(rootFileDir, curFileName) |
+ if err != nil { |
+ log.Fatalln(err.Error()) |
+ } |
+ result = append(result, rel) |
+ |
+ if curFile.Imports != nil { |
+ for _, importFileName := range *curFile.Imports { |
+ toVisit = append(toVisit, importFileName) |
+ } |
+ } |
+ } |
+ return |
+} |