[Laszlo-checkins] r10645 - openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc

dda@openlaszlo.org dda at openlaszlo.org
Sat Aug 9 07:05:18 PDT 2008


Author: dda
Date: 2008-08-09 07:05:13 -0700 (Sat, 09 Aug 2008)
New Revision: 10645

Modified:
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9External.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/TranslationUnit.java
Log:
Change 20080808-dda-K by dda at lester.local on 2008-08-08 14:28:43 EDT
    in /Users/dda/laszlo/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: SWF9: allow class and global var names to differ only in case.

New Features:

Bugs Fixed: LPP-6792 (class 'Foo' and top level var 'foo' cannot coexist in SWF9 programs)

Technical Reviewer: ptw (pending)
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
    Use subdirectory naming as discussed in LPP-6792 to distinguish class names and variable names.
    We also allow classes and variable names to be the same (var foo = new foo()), as flex seems to accept this.
    More details on the implementation contained in javadoc for the changed files.

Tests:
    Regression: smokecheck (swf8+dhtml), (lzpix+weather)(swf8+swf9+dhtml)

    Temporarily added the following test code to LzNode.lzs, and verified that produced output files
    end up in the right subdirectories:

========
class Global1 {
  public function x() {}
}

class GLOBAL2 {
}

class GLOBAL3 {
}

class global2 {
}

var Global1 = 6;
var GloBal1 = -1;
var global1 = 7;
//var global1 = 8;  // should give an error

class global1 {
  public function y() {}
}

//class global1 {}  // should give an error

var foo = new global1();
foo.y();

class global3 {
}
class Global1 {
========




Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java	2008-08-09 08:30:05 UTC (rev 10644)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java	2008-08-09 14:05:13 UTC (rev 10645)
@@ -1333,6 +1333,7 @@
           case ANNOTATE_OP_CLASSNAME:
             curtu = new TranslationUnit();
             curtu.setName(operand);
+            curtu.setIsClass(true);
             tunits.add(curtu);
             return "";
           case ANNOTATE_OP_INSERTSTREAM:

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9External.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9External.java	2008-08-09 08:30:05 UTC (rev 10644)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9External.java	2008-08-09 14:05:13 UTC (rev 10645)
@@ -53,11 +53,21 @@
   private File workdir = createCompilationWorkDir();
   private Compiler.OptionMap options;
 
-  /**
-   * The key is the 'tolower' name, the value is the actual name.
+  /*
+   * Used by getFileNameForClassName to prevent filename conflicts.
+   * The key is the 'tolower' name, the value is an ArrayList of
+   * UniqueGlobalName objects.
    */
   private HashMap uniqueFileNames = new HashMap();
 
+  public class UniqueGlobalName {
+    String globalName;
+    boolean isClass;
+    int subdirnum;    // subdirector number, 0 means top level
+  }
+
+  private int maxSubdirnum = 0;
+
   public SWF9External(Compiler.OptionMap options) {
     this.options = options;
   }
@@ -619,6 +629,9 @@
     }
 
     cmd.add("-compiler.source-path+=" + workdir.getPath());
+    for (int i=1; i<=maxSubdirnum; i++) {
+      cmd.add("-compiler.source-path+=" + workdir.getPath() + File.separator + i);
+    }
     if (options.getBoolean(Compiler.DEBUG_SWF9)) {
       cmd.add("-debug=true");
     }
@@ -656,23 +669,69 @@
   }
 
   /**
-   * Checks for unique file names for files written.
-   * We do not allow files to match, or even to be differing
-   * only by case.  The latter will cause problems on
-   * file systems that merge upper/lower case names.
-   * @throw CompilerError for file name conflicts
+   * Get a unique file name for the class or global variable.  Flex
+   * requires that classes and global variables must be defined
+   * within matching file names.  For example 'var FooBar' must be in
+   * FooBar.as, and 'class foobar' must be in foobar.as.  But some
+   * file systems (like FAT32 and AFS+) do not allow file names in the
+   * same directory that only differ by case.  In order to allow
+   * names that differ by case, we use subdirectories on an as needed
+   * basis.  For example, if we see names in the order:
+   * "foo" "fOO" "BAR" "Foo" "bar"
+   * the file/directory names will be used:
+   * <pre>
+   *  "./foo.as"
+   *  "./1/fOO.as"
+   *  "./bar.as"
+   *  "./2/Foo.as"
+   *  "./1/bar.as"
+   * </pre>
+   * This system guarantees usable file names on all systems,
+   * normally keeping all files in the top level directory, and
+   * minimizes the number of subdirectories.  Each subdirectory
+   * requires an additional '-compiler.source-path+=...' argument
+   * to flex, and we'd rather not test whether there is a limit.
+   *
+   * This method also checks for class/global var names that have been
+   * used before and throws an error.
+   *
+   * A side effect of this method is to set the maxSubdirnum to the
+   * maximum of the subdirectory numbers used.
+   *
+   * @throw CompilerError for class/var names used previously.
    */
-  void checkFileNameForClassName(String name) {
+  private String getFileNameForClassName(String name, boolean isClass) {
     String lower = name.toLowerCase();
-    String existing;
-    if ((existing = (String)uniqueFileNames.get(lower)) != null) {
-      if (existing.equals(name)) {
-        throw new CompilerError("cannot declare class name more than once: \"" + name + "\"");
-      } else {
-        throw new CompilerError("class names only differ by upper/lower case: \"" + existing + "\" versus \"" + name + "\"");
+    List list = (List)uniqueFileNames.get(lower);
+
+    if (list == null) {
+      list = new ArrayList();
+      uniqueFileNames.put(lower, list);
+    } else {
+      for (Iterator iter = list.iterator(); iter.hasNext(); ) {
+        UniqueGlobalName unique = (UniqueGlobalName)iter.next();
+        if (name.equals(unique.globalName) && isClass == unique.isClass) {
+          String what = isClass ? "class" : "global var";
+          throw new CompilerError("cannot declare " + what +
+                                  " name more than once: \"" + name + "\"");
+        }
       }
     }
-    uniqueFileNames.put(lower, name);
+    int dirnum = list.size();
+    UniqueGlobalName unique = new UniqueGlobalName();
+    unique.globalName = name;
+    unique.isClass = isClass;
+    unique.subdirnum = dirnum;
+    list.add(unique);
+    String subdirname = workdir.getPath();
+    if (dirnum > 0) {
+      subdirname += File.separator + dirnum;
+    }
+    if (dirnum > maxSubdirnum) {
+      (new File(subdirname)).mkdirs();
+      maxSubdirnum = dirnum;
+    }
+    return subdirname + File.separator + name + ".as";
   }
 
   /**
@@ -695,8 +754,7 @@
   public void writeFile(TranslationUnit tunit, String pre, String post) {
     String name = tunit.getName();
     String body = tunit.getContents();
-    checkFileNameForClassName(name);
-    String infilename = workdir.getPath() + File.separator + name + ".as";
+    String infilename = getFileNameForClassName(name, tunit.isClass());
     tunit.setSourceFileName(infilename);
     tunit.setLineOffset(countLines(pre));
 

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java	2008-08-09 08:30:05 UTC (rev 10644)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java	2008-08-09 14:05:13 UTC (rev 10645)
@@ -699,6 +699,7 @@
 
       TranslationUnit tunit = new TranslationUnit();
       tunit.setName(varname);
+      tunit.setIsClass(false);
       String decl = "public var " + varname;
       if (glovar.type != null)
         decl += ":" + glovar.type;

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/TranslationUnit.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/TranslationUnit.java	2008-08-09 08:30:05 UTC (rev 10644)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/TranslationUnit.java	2008-08-09 14:05:13 UTC (rev 10645)
@@ -28,6 +28,7 @@
   private boolean isMain = false;    // designated classes, like LFCApplication
   private Map streams = new HashMap(); // alternate streams, indexed by number
   private int maxInserts = 0;          // bound the number of stream insert replacements
+  private boolean isClass = true;
 
   // When these appear in the contents they will be replaced
   // by the indicated stream whenever contents is retrieved.
@@ -88,6 +89,14 @@
     isMain = value;
   }
 
+  public boolean isClass() {
+    return isClass;
+  }
+
+  public void setIsClass(boolean isClass) {
+    this.isClass = isClass;
+  }
+
   public void addText(String s) {
     text.append(s);
     linenum += countOccurence(s, '\n');



More information about the Laszlo-checkins mailing list