logo
class

compiler::WritePod

sys::Obj
  compiler::CompilerSupport
    compiler::CompilerStep
      compiler::WritePod
   1  //
   2  // Copyright (c) 2006, Brian Frank and Andy Frank
   3  // Licensed under the Academic Free License version 3.0
   4  //
   5  // History:
   6  //   3 Sep 05  Brian Frank  Creation
   7  //   7 Oct 06  Brian Frank  Port from Java to Fan
   8  //
   9  
  10  **
  11  ** WritePod writes the FPod to a zip file.
  12  **
  13  class WritePod : CompilerStep
  14  {
  15  
  16  //////////////////////////////////////////////////////////////////////////
  17  // Constructor
  18  //////////////////////////////////////////////////////////////////////////
  19  
  20    new make(Compiler compiler)
  21      : super(compiler)
  22    {
  23    }
  24  
  25  //////////////////////////////////////////////////////////////////////////
  26  // Run
  27  //////////////////////////////////////////////////////////////////////////
  28  
  29    **
  30    ** Not used, use write instead
  31    **
  32    override Void run() { throw UnsupportedErr.make }
  33  
  34    **
  35    ** Run the step and return pod file written
  36    **
  37    File write()
  38    {
  39      dir  := compiler.input.outDir
  40      fpod := compiler.fpod
  41      podFile := dir + "${fpod.name}.pod".toUri
  42      location = Location.makeFile(podFile)
  43  
  44      log.message("WritePod", podFile.toStr)
  45  
  46      // create output directory
  47      dir.create
  48  
  49      Zip zip := null
  50      try
  51      {
  52        // open zip store
  53        zip = Zip.write(podFile.out)
  54  
  55        // write fpod data structures into zip file
  56        fpod.write(zip)
  57  
  58        // write resource files
  59        compiler.resFiles.each |File f| { writeRes(zip, f) }
  60  
  61        // if including fandoc write it out too
  62        if (compiler.input.includeDoc) writeTypeDocs(zip)
  63  
  64        // if including source write it out too
  65        if (compiler.input.includeSrc) writeSrc(zip)
  66      }
  67      catch (CompilerErr e)
  68      {
  69        throw e
  70      }
  71      catch (Err e)
  72      {
  73        throw errReport(CompilerErr.make("Cannot write", location, e))
  74      }
  75  
  76      // close file
  77      if (zip != null) zip.close
  78      return podFile
  79    }
  80  
  81  //////////////////////////////////////////////////////////////////////////
  82  // Resource
  83  //////////////////////////////////////////////////////////////////////////
  84  
  85    private Void writeRes(Zip zip, File file, Uri path := null)
  86    {
  87      input := compiler.input
  88      if (path == null)
  89      {
  90        path = file.uri
  91        path = path - input.homeDir.uri
  92      }
  93  
  94      try
  95      {
  96        out := zip.writeNext(path, file.modified)
  97        file.in.pipe(out)
  98        out.close
  99      }
 100      catch (Err e)
 101      {
 102        throw errReport(CompilerErr.make("Cannot write resource file '$path'", location, e))
 103      }
 104    }
 105  
 106  //////////////////////////////////////////////////////////////////////////
 107  // Doc
 108  //////////////////////////////////////////////////////////////////////////
 109  
 110    private Void writeTypeDocs(Zip zip)
 111    {
 112      compiler.types.each |TypeDef t|
 113      {
 114        if (!t.isSynthetic) writeTypeDoc(zip, t)
 115      }
 116    }
 117  
 118    private Void writeTypeDoc(Zip zip, TypeDef t)
 119    {
 120      try
 121      {
 122        out := zip.writeNext("doc/${t.name}.apidoc".toUri)
 123        writeDoc(out, t.qname, t.doc)
 124        t.slotDefs.each |SlotDef s|
 125        {
 126          writeDoc(out, s.qname, s.doc)
 127        }
 128        out.close
 129      }
 130      catch (Err e)
 131      {
 132        throw errReport(CompilerErr.make("Cannot write fandoc '$t.name'", t.location, e))
 133      }
 134    }
 135  
 136    **
 137    ** FDoc is used to read/write a fandoc text file.  The fandoc file
 138    ** format is an extremely simple plan text format with left justified
 139    ** type/slot qnames, followed by the fandoc content indented two spaces.
 140    **
 141    private static Void writeDoc(OutStream out, Str key, Str[] doc)
 142    {
 143      if (doc == null) return
 144      out.printLine(key)
 145      doc.each |Str line| { out.print("  ").printLine(line) }
 146      out.printLine
 147    }
 148  
 149  //////////////////////////////////////////////////////////////////////////
 150  // Src
 151  //////////////////////////////////////////////////////////////////////////
 152  
 153    private Void writeSrc(Zip zip)
 154    {
 155      compiler.srcFiles.each |File f|
 156      {
 157        writeRes(zip, f, "src/$f.name".toUri)
 158      }
 159    }
 160  
 161  //////////////////////////////////////////////////////////////////////////
 162  // Fields
 163  //////////////////////////////////////////////////////////////////////////
 164  
 165    private Location location
 166  }