Author: hqm
Date: 2007-10-23 20:14:32 -0700 (Tue, 23 Oct 2007)
New Revision: 6984

Added:
   openlaszlo/trunk/test/compiler_errors/attribute-overrides-method.lzx
   openlaszlo/trunk/test/compiler_errors/method-override.lzx
   openlaszlo/trunk/test/compiler_errors/override-x-attribute.lzx
Modified:
   openlaszlo/trunk/WEB-INF/lps/schema/lfc.lzx
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/AttributeSpec.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
   
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/xml/internal/Schema.java
Log:
Change 20071023-hqm-6 by [EMAIL PROTECTED] on 2007-10-23 23:07:13 EDT
    in /cygdrive/c/users/hqm/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary:  make better LZX compiler warnings for colliding attribute names

New Features:

Bugs Fixed: LPP-3910

Technical Reviewer: ptw
QA Reviewer: dda
Doc Reviewer:

Documentation:

Release Notes:

Details:

Use AttributeSpec to store declared methods in addition to attributes, so it's
easier to detect attributes overriding methods and vice versa.

Add or improve various warnings

   

Tests:

ant test
ant lztest
compile webtop mail app
demos

verify that the compiled javascript is same after this patch as before on
smokecheck and webtop app




Modified: openlaszlo/trunk/WEB-INF/lps/schema/lfc.lzx
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/schema/lfc.lzx 2007-10-24 02:30:16 UTC (rev 
6983)
+++ openlaszlo/trunk/WEB-INF/lps/schema/lfc.lzx 2007-10-24 03:14:32 UTC (rev 
6984)
@@ -13,15 +13,31 @@
  * P_LZ_COPYRIGHT_END ********************************************************
 -->
 
+
+<interface name="Instance" extends="Object">
+  <method name="validateClassStructure" override="false"/>
+  <method name="initialize" override="false"/>
+  <method name="nextMethod" override="false"/>
+  <method name="addProperty" override="false"/>
+  <method name="constructor" override="false"/>
+  <method name="hasOwnProperty" override="false"/>
+  <method name="isPropertyEnumerable" override="false"/>
+  <method name="isPrototypeOf" override="false"/>
+  <method name="toLocaleString" override="false"/>
+  <method name="prototype" override="false"/>
+  <method name="apply" override="false"/>
+  <method name="call" override="false"/>
+</interface>
+
 <interface name="canvas" extends="Instance">
   <attribute name="id" type="ID"/>
   <!--   The oninit script is executed once, after the element's
          children, if any, have been initialized. -->
   <event name="oninit"/>
   <!--  The width of the canvas. -->
-  <attribute name="width" type="sizeExpression" value="500"/>
+  <attribute name="width" type="size" value="500"/>
   <!--  The height of the canvas. -->
-  <attribute name="height" type="sizeExpression" value="400"/>
+  <attribute name="height" type="size" value="400"/>
   <!-- The background color of the canvas. -->
   <attribute name="bgcolor" type="color" value="white"/>
   <!-- The string that is used in the browser window. -->
@@ -112,6 +128,10 @@
   -->
   <event name="oninit"/>
   <event name="ondata"/>
+  <event name="onconstruct"/>
+  <event name="onclonenumber"/>
+  <event name="ondestroy"/>
+
   <attribute name="initstage" type="string" value="normal" 
enum="early|normal|late|immediate|defer"/>
   <attribute name="datapath" type="string"/>
   <attribute name="placement" type="string"/>
@@ -141,7 +161,7 @@
   <attribute name="fgcolor" type="color"/>
   <attribute name="font" type="string"/>
   <attribute name="fontstyle" type="string"/>
-  <attribute name="fontsize" type="sizeExpression"/>
+  <attribute name="fontsize" type="size"/>
   <attribute name="resource" type="string"/>
   <attribute name="source" type="expression" />
   <attribute name="clip" type="boolean" value="false"/>
@@ -157,8 +177,8 @@
   <attribute name="stretches" type="string" enum="width|height|both"/>
   <attribute name="visible" type="expression" value="true"/>
   <attribute name="visibility" type="string" value="visibility"/>
-  <attribute name="width" type="sizeExpression"/>
-  <attribute name="height" type="sizeExpression"/>
+  <attribute name="width" type="size"/>
+  <attribute name="height" type="size"/>
   <attribute name="x" type="numberExpression" value="0"/>
   <attribute name="y" type="numberExpression" value="0"/>
   <attribute name="aaname" type="string"/>
@@ -167,17 +187,49 @@
   <attribute name="aatabindex" type="number"/>
   <attribute name="aasilent" type="boolean"/>
   <attribute name="showhandcursor" type="boolean"/>
+  <event name="onaddsubresource"/>
+  <event name="onaddsubview"/>
+  <event name="onbgcolor"/>
+  <event name="onblur"/>
   <event name="onclick"/>
   <event name="ondblclick"/>
-  <event name="onmousedown"/>
-  <event name="onmouseup"/>
-  <event name="onmouseover"/>
-  <event name="onmouseout"/>
+  <event name="onerror"/>
   <event name="onfocus"/>
-  <event name="onblur"/>
+  <event name="onframe"/>
+  <event name="onheight"/>
+  <event name="onimload"/>
   <event name="onkeydown"/>
   <event name="onkeyup"/>
+  <event name="onlastframe"/>
+  <event name="onload"/>
+  <event name="onloadperc"/>
+  <event name="onmousedown"/>
+  <event name="onmouseout"/>
+  <event name="onmouseover"/>
+  <event name="onmousetrackover"/>
+  <event name="onmousetrackup"/>
+  <event name="onmouseup"/>
+  <event name="onopacity"/>
+  <event name="onplay"/>
+  <event name="onremovesubview"/>
+  <event name="onresource"/>
+  <event name="onresourceheight"/>
+  <event name="onresourcewidth"/>
+  <event name="onrotation"/>
   <event name="onselect"/>
+  <event name="onstop"/>
+  <event name="ontimeout"/>
+  <event name="ontotalframes"/>
+  <event name="onunstretchedheight"/>
+  <event name="onunstretchedwidth"/>
+  <event name="onvisibility"/>
+  <event name="onvisible"/>
+  <event name="onwidth"/>
+  <event name="onx"/>
+  <event name="onxoffset"/>
+  <event name="ony"/>
+  <event name="onyoffset"/>
+  
   <containsElements>
     <element>dataselectionmanager</element>
     <element>selectionmanager</element>
@@ -367,7 +419,7 @@
   <!-- This controls the spacing between elements if <a
        href="datapath.html#attr-replication">lazy replication</a> is
        true -->
-  <attribute name="spacing" type="sizeExpression" value="0"/>
+  <attribute name="spacing" type="size" value="0"/>
   <attribute name="p" type="expression"/>
 </interface>
 
@@ -451,7 +503,9 @@
 </interface>
 
 <interface name="state" extends="node">
-  <attribute name="apply" type="boolean"/>
+  <!-- This is unfortunately both a setter attribute AND a method. No
+       real nice way to represent that. -->
+  <method name="apply" override="true" />
   <!-- If pooling is true, views that are created by the state are not
        destroyed when the state is removed - instead they just act as
        if they were by sending the onremovesubview event and setting

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/AttributeSpec.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/AttributeSpec.java
  2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/AttributeSpec.java
  2007-10-24 03:14:32 UTC (rev 6984)
@@ -18,7 +18,7 @@
     /** The attribute name */
     String name;
     /** The default value */
-    String defaultValue;
+    String defaultValue = null;
     /** The setter function */
     String setter;
     /** The type of the attribute value*/ 
@@ -28,6 +28,12 @@
     /** When does the initial value for this attribute get evaluated? */
     String when = NodeModel.WHEN_IMMEDIATELY;
 
+    /** If this is a method, the arglist */
+    String arglist = null;
+
+    /** Can this attribute be overridden without a warning? value is null, 
'true' or 'false' */
+    String override = null;
+
     /** Is this attribute equivalent to element content of a given type? */
     int contentType = NO_CONTENT;
 
@@ -49,6 +55,10 @@
 
   public String toLZX(String indent, ClassModel superclass) {
     AttributeSpec superSpec = superclass.getAttribute(name);
+    if (ViewSchema.METHOD_TYPE.equals(type)) {
+      return indent + "  <method name='" + name + "'" + 
(("".equals(arglist))?"":(" args='" + arglist +"'")) + " />";
+    }
+
     if (superSpec == null) {
       if (ViewSchema.EVENT_HANDLER_TYPE.equals(type)) {
         return indent + "<event name='" + name + "' />";
@@ -82,6 +92,21 @@
     }
     return null;
   }
+
+  public String toString() {
+    if (ViewSchema.METHOD_TYPE.equals(type)) {
+      return "[AttributeSpec: method name='" + name + "'" + 
(("".equals(arglist))?"":(" args='" + arglist +"'")) + " override="+(override  
== null ?  "null" : ("'"+override+"'"))+"]";
+    } 
+    if (ViewSchema.EVENT_HANDLER_TYPE.equals(type)) {
+      return "[AttributeSpec: event name='" + name + "' ]";
+    }
+    return "[AttributeSpec: attribute name='" + name + "'" +
+        ((defaultValue != null)?(" value='" + defaultValue + "'"):"") +
+        ((type != null)?(" type='" + typeToLZX() + "'"):"") +
+        ((when != NodeModel.WHEN_IMMEDIATELY)?(" when='" + when + "'"):"") + 
+        (required?(" required='true'"):"") +
+        " ";
+  }
     
     AttributeSpec (String name, Type type, String defaultValue, String setter, 
Element source) {
         this.source = source;

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
  2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
  2007-10-24 03:14:32 UTC (rev 6984)
@@ -127,9 +127,29 @@
             Object o = iterator.next();
             if (o instanceof Element) {
                 Element child = (Element) o;
+                if (child.getName().equals("method")) {
+                    String attrName = child.getAttributeValue("name");
+                    String attrEvent = child.getAttributeValue("event");
+                    if (attrEvent == null) {
+                        if (schema.enforceValidIdentifier) {
+                            try {
+                                attrName = 
requireIdentifierAttributeValue(child, "name");
+                            } catch (MissingAttributeException e) {
+                                throw new CompilationError(
+                                    "'name' is a required attribute of <" + 
child.getName() + "> and must be a valid identifier", child);
+                            }
+                        }
+                        ViewSchema.Type attrType = ViewSchema.METHOD_TYPE;
+                        AttributeSpec attrSpec = 
+                            new AttributeSpec(attrName, attrType, null, null, 
child);
+                        attrSpec.override = 
child.getAttributeValue("override");
+                        attributeDefs.add(attrSpec);
+                    }
+                    
+                } else if (child.getName().equals("attribute")) {
                 // Is this an element named ATTRIBUTE which is a
                 // direct child of this CLASS or INTERFACE tag?
-                if (child.getName().equals("attribute")) {
+
                     String attrName = child.getAttributeValue("name");
                     if (schema.enforceValidIdentifier) {
                         try {
@@ -179,6 +199,7 @@
                     AttributeSpec attrSpec = 
                         new AttributeSpec(attrName, attrType, attrDefault,
                                           attrSetter, child);
+                    attrSpec.override = child.getAttributeValue("override");
                     if (attrName.equals("text") && attrTypeName != null) {
                         if ("text".equals(attrTypeName))
                             attrSpec.contentType = attrSpec.TEXT_CONTENT;
@@ -208,7 +229,7 @@
         }
         
         // Add this class to the schema
-        schema.addElement(element, classname, superclass, attributeDefs);
+        schema.addElement(element, classname, superclass, attributeDefs, mEnv);
     }
     
     public void compile(Element elt) {

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java 
    2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java 
    2007-10-24 03:14:32 UTC (rev 6984)
@@ -29,8 +29,7 @@
     protected boolean supportsTextAttribute = false;
     /** Map attribute name to type */
     protected final Map attributeSpecs = new LinkedHashMap();
-    /** Map of method names to arglist */
-    protected final Map methods = new LinkedHashMap();
+
     protected boolean inline = false;
     protected String sortkey = null;
 
@@ -82,14 +81,7 @@
         lzx += specLZX;
       }
     }
-    for (Iterator i = methods.entrySet().iterator(); i.hasNext(); ) {
-      Map.Entry entry = (Map.Entry)i.next();
-      String name = (String)entry.getKey();
-      String arglist = (String)entry.getValue();
-      if (superclass.getMethod(name) == null) {
-        lzx += "\n" + indent + "  <method name='" + name + "'" + 
(("".equals(arglist))?"":(" args='" + arglist +"'")) + " />";
-      }
-    }
+
     lzx += "\n" + indent + "</interface>";
     return lzx;
   }
@@ -130,6 +122,14 @@
         }
     }
     
+    /** Return the AttributeSpec for the attribute named attrName.
+        Only returns locally defined attribute, does not follow up the
+        class hierarchy.
+    */
+    AttributeSpec getLocalAttribute(String attrName) {
+      return (AttributeSpec) attributeSpecs.get(attrName);
+    }
+
     /** Return the AttributeSpec for the attribute named attrName.  If
      * the attribute is not defined on this class, look up the
      * superclass chain.
@@ -198,23 +198,6 @@
         return type;
     }
     
-    /** Return the 'MethodSpec' for the method named methName.  If
-     * the method is not defined on this class, look up the
-     * superclass chain.
-     * TODO: [2007-01-27 ptw] For now the MethodSpec is just the
-     * arglist String
-     */
-    String getMethod(String methName) {
-        String meth = (String) methods.get(methName);
-        if (meth != null) {
-            return meth;
-        } else if (superclass != null) {
-            return(superclass.getMethod(methName));
-        } else {
-            return null;
-        }
-    }
-
     void setNodeModel(NodeModel model) {
         this.nodeModel = model;
     }

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java   
    2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java   
    2007-10-24 03:14:32 UTC (rev 6984)
@@ -370,6 +370,17 @@
             // If we are not linking, then we consider all external
             // files to have already been imported.
             if (! linking) { externalLibraries = 
env.getImportedLibraryFiles(); }
+            if (root.getName().intern() != 
+                (linking ? "canvas" :  "library")) {
+                throw new CompilationError(
+/* (non-Javadoc)
+ * @i18n.test
+ * @org-mes="invalid root element type: " + p[0]
+ */
+            org.openlaszlo.i18n.LaszloMessages.getMessage(
+                Compiler.class.getName(),"051018-357", new Object[] 
{root.getName()})
+                );
+            }
             Compiler.updateRootSchema(root, env, schema, externalLibraries);
             Properties nprops = (Properties) env.getProperties().clone();
             Map compileTimeConstants = new HashMap();
@@ -406,17 +417,6 @@
 
 
             mLogger.debug("new env..." + env.getProperties().toString());
-            if (root.getName().intern() != 
-                (linking ? "canvas" :  "library")) {
-                throw new CompilationError(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="invalid root element type: " + p[0]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                Compiler.class.getName(),"051018-357", new Object[] 
{root.getName()})
-                );
-            }
             
             processCompilerInstructions(root, env);
             compileElement(root, env);
@@ -613,17 +613,29 @@
     static void updateRootSchema(Element root, CompilationEnvironment env,
                                  ViewSchema schema, Set externalLibraries)
     {
-      ToplevelCompiler ec = (ToplevelCompiler)getElementCompiler(root, env);
-      Set visited = new HashSet();
-      // Update schema for auto-includes
-      // Note:  this call does _not_ share visited with the update
-      // calls intentionally.
-      for (Iterator iter = ec.getLibraries(env, root, null, externalLibraries, 
new HashSet()).iterator();
-           iter.hasNext(); ) {
-        File library = (File) iter.next();
-        Compiler.updateSchemaFromLibrary(library, env, schema, visited);
-      }
-      ec.updateSchema(root, schema, visited);
+        ElementCompiler ecompiler = getElementCompiler(root, env);
+        if (! (ecompiler  instanceof ToplevelCompiler)) {
+            throw new CompilationError(
+/* (non-Javadoc)
+ * @i18n.test
+ * @org-mes="invalid root element type: " + p[0]
+ */
+            org.openlaszlo.i18n.LaszloMessages.getMessage(
+                Compiler.class.getName(),"051018-357", new Object[] 
{root.getName()})
+                );
+            }
+        ToplevelCompiler tlc = (ToplevelCompiler) ecompiler;
+
+        Set visited = new HashSet();
+        // Update schema for auto-includes
+        // Note:  this call does _not_ share visited with the update
+        // calls intentionally.
+        for (Iterator iter = tlc.getLibraries(env, root, null, 
externalLibraries, new HashSet()).iterator();
+             iter.hasNext(); ) {
+            File library = (File) iter.next();
+            Compiler.updateSchemaFromLibrary(library, env, schema, visited);
+        }
+        tlc.updateSchema(root, schema, visited);
     }
 
     static void updateSchema(Element element, CompilationEnvironment env,

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java  
    2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java  
    2007-10-24 03:14:32 UTC (rev 6984)
@@ -585,11 +585,6 @@
             // global there is "id='foo'" or if "name='foo'" at the
             // top level (immediate child of the canvas).
             //
-            // NB: since this finds class names via a lookup from
-            // elements in the schema, it will give some false
-            // positives on class-name collisions, such as tag names
-            // like "audio" which do not actually correspond to a LFC
-            // class at runtime.
             if ((name.equals("id")) ||
                 (name.equals("name") &&
                  topLevelDeclaration() && !className.equals("class"))) {
@@ -890,21 +885,19 @@
         return (child.getName().equals("datapath"));
     }
 
-    void checkChildNameConflict(Element child, CompilationEnvironment env) {
+    /** Warn if named child tag conflicts with a declared attribute in the 
parent class.
+     */
+    void checkChildNameConflict(String parentName, Element child, 
CompilationEnvironment env) {
         String attrName = child.getAttributeValue("name");
         if (attrName != null) {
-            ViewSchema.Type attrType = null;
-            try {
-                attrType = schema.getAttributeType(element,  attrName);
-            } catch (UnknownAttributeException e) {
-                    
-            }
-            if (attrType != null) {
+            AttributeSpec attrSpec = schema.getClassAttribute ( parentName, 
attrName) ;
+            // Only warn if the attribute we are shadowing has a declared 
initial value.
+            if (attrSpec != null && attrSpec.defaultValue != null) {
                 // TODO [2007-09-26 hqm] i18n this
                 env.warn(
                     "Child tag '" + child.getName() +
                     "' with attribute '"+attrName +
-                    "' conflicts with attribute named '"+attrName+"' of type 
'" + attrType +
+                    "' conflicts with attribute named '"+attrName+"' of type 
'" + attrSpec.type +
                     "' on parent tag '"+element.getName()+"'.",
                     element);
             }
@@ -927,7 +920,7 @@
 
             try {
                 if (child.getName().equals("data")) {
-                    checkChildNameConflict(child, env);
+                    checkChildNameConflict(element.getName(), child, env);
                     // literal data
                     addLiteralDataElement(child);
                 } else if (isPropertyElement(child)) {
@@ -937,11 +930,11 @@
                 } else if (schema.isDocElement(child)) {
                     ; // ignore doc nodes.
                 } else if (isDatapathElement(child)) {
-                    checkChildNameConflict(child, env);
+                    checkChildNameConflict(element.getName(), child, env);
                     NodeModel dpnode = elementAsModel(child, schema, env);
                     this.datapath = dpnode;
                 } else {
-                    checkChildNameConflict(child, env);
+                    checkChildNameConflict(element.getName(), child, env);
                     NodeModel childModel = elementAsModel(child, schema, env);
                     children.add(childModel);
                     totalSubnodes += childModel.totalSubnodes();
@@ -1110,6 +1103,7 @@
         String name = element.getAttributeValue("name");
         String event = element.getAttributeValue("event");
         String args = XMLUtils.getAttributeValue(element, "args", "");
+
         if ((name == null || !ScriptCompiler.isIdentifier(name)) &&
             (event == null || !ScriptCompiler.isIdentifier(event))) {
             env.warn(
@@ -1148,12 +1142,6 @@
                  CompilerUtils.attributeUniqueName(element, "event") :
                  CompilerUtils.attributeUniqueName(element, "name"));
         }
-        if (name != null && "class".equals(className)) {
-          schema.addMethodDeclaration(element,
-                                      
element.getParentElement().getAttributeValue("name"),
-                                      name, args);
-        }
-
         if (event != null) {
             if (name == null) {
                 // Names have to be unique across binary libraries, so
@@ -1210,6 +1198,12 @@
                 ,element);
         }
 
+
+        /**
+           TODO [hqm 2007-10-21]
+           WARN if method attributespec has override=false
+        **/
+
         attrs.put(name, fndef);
     }
 
@@ -1385,6 +1379,8 @@
                 if (when.equals(WHEN_IMMEDIATELY)) {
                     when = WHEN_ONCE;
                 }
+            } else if (type == ViewSchema.METHOD_TYPE) {
+                // methods are emitted elsewhere
             } else {
                 throw new RuntimeException("unknown schema datatype " + type);
             }
@@ -1526,6 +1522,7 @@
                 parenttype = getAttributeTypeInfoFromSuperclass(parent, name);
             }  else {
                 parenttype = schema.getAttributeType(parent, name);
+
             }
         } catch (UnknownAttributeException e) {
             // If attribute type is not defined on parent, leave
@@ -1574,6 +1571,18 @@
             }
         }
 
+        // Warn if we are overidding a method, handler, or other function
+        if (parenttype == schema.METHOD_TYPE ||
+            parenttype == schema.EVENT_HANDLER_TYPE ||
+            parenttype == schema.SETTER_TYPE ||
+            parenttype == schema.REFERENCE_TYPE) {
+            env.warn( "In element '" + parent.getName() 
+                      + "' attribute '" +  name 
+                      + "' is overriding parent class attribute which has the 
same name but type: "
+                      + parenttype.toString(),
+                      element);
+        }
+
         // Don't initialize an attribute that is only declared.
         if (value != null) {
             CompiledAttribute cattr = compileAttribute(element, name,

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java 
    2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java 
    2007-10-24 03:14:32 UTC (rev 6984)
@@ -78,12 +78,14 @@
     public static final Type TOKEN_TYPE = newType("token");
     public static final Type COLOR_TYPE = newType("color");
     public static final Type NUMBER_EXPRESSION_TYPE = 
newType("numberExpression");
-    public static final Type SIZE_EXPRESSION_TYPE = newType("sizeExpression");
+    public static final Type SIZE_EXPRESSION_TYPE = newType("size");
     public static final Type CSS_TYPE = newType("css");
     public static final Type INHERITABLE_BOOLEAN_TYPE = 
newType("inheritableBoolean");
     public static final Type XML_LITERAL = newType("xmlLiteral");
+    public static final Type METHOD_TYPE = newType("method");
     
     static {
+
         sHTMLContentElements.add("text");
         sInputTextElements.add("inputtext");
 
@@ -171,7 +173,13 @@
         }
     }
 
-    public void addMethodDeclaration (Element elt, String classname, String 
methodName, String arglist) {
+    /** Checks to do when declaring a method on a class;
+     * Does the class exist?
+     * Is this a duplicate of another method declaration on this class?
+     * Does the superclass allow overriding of this method?
+     */
+    public void checkMethodDeclaration (Element elt, String classname, String 
methodName,
+                                        CompilationEnvironment env) {
         ClassModel classModel = getClassModel(classname);
         if (classModel == null) {
             throw new RuntimeException(
@@ -181,19 +189,31 @@
  */
             org.openlaszlo.i18n.LaszloMessages.getMessage(
                 ViewSchema.class.getName(),"051018-168", new Object[] 
{classname})
-);
+                                       );
         }
-        if (classModel.methods.get(methodName) != null) {
-            throw new CompilationError(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="duplicate definition of method " + p[0] + "." + p[1]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-207", new Object[] 
{classname, methodName})
-, elt);
+        AttributeSpec localAttr = classModel.getLocalAttribute(methodName);
+        if ( localAttr != null) {
+            if (localAttr.type == METHOD_TYPE) {
+                env.warn(
+                    /* (non-Javadoc)
+                     * @i18n.test
+                     * @org-mes="duplicate definition of method " + p[0] + "." 
+ p[1]
+                     */
+                    org.openlaszlo.i18n.LaszloMessages.getMessage(
+                        ViewSchema.class.getName(),"051018-207", new Object[] 
{classname, methodName}),
+                    elt);
+            } else {
+                env.warn(
+                    "Method named "+methodName+" on class "+classname+
+                    " conflicts with attribute with named "+methodName+" and 
type "+localAttr.type,
+                    elt);
+            }
         }
-        classModel.methods.put(methodName, arglist);
+
+        if (!methodOverrideAllowed(classname, methodName)) {
+            env.warn("Method "+classname+"."+methodName+" is overriding a 
superclass method"
+                     + " of the same name which has been declared 
non-overridable" , elt);
+        }
     }
 
     public String getSuperclassName(String className) {
@@ -246,7 +266,8 @@
      * @param attributeDefs list of attribute name/type defs
      */
     public void addElement (Element elt, String className,
-                            String superclassName, List attributeDefs)
+                            String superclassName, List attributeDefs,
+                            CompilationEnvironment env)
     {
         ClassModel superclass = getClassModel(superclassName);
 
@@ -312,7 +333,7 @@
         }
 
         // Add in the attribute declarations
-        addAttributeDefs(elt, className, attributeDefs);
+        addAttributeDefs(elt, className, attributeDefs, env);
     }
 
     /**
@@ -323,7 +344,8 @@
      * @param attributeDefs list of AttributeSpec attribute info to add to the 
Schema
      *
      */
-    void addAttributeDefs (Element sourceElement, String classname, List 
attributeDefs)
+    void addAttributeDefs (Element sourceElement, String classname, List 
attributeDefs,
+                           CompilationEnvironment env)
     {
         if (!attributeDefs.isEmpty()) {
             for (Iterator iter = attributeDefs.iterator(); iter.hasNext();) {
@@ -336,25 +358,26 @@
                 // redefining an attribute of a parent class with a
                 // different type.
 
-                if (getClassAttribute(classname, attr.name) == null) {
-                    // Splice some XML into the Schema element
-                    String attrTypeName = attr.type.toString();
-                } else {
+                Type parentType = null;
+                if (getClassAttribute(classname, attr.name) != null) {
                     // Check that the overriding type is the same as the 
superclass' type
-                    Type parentType = getAttributeType(classname, attr.name);
+                    parentType = getAttributeType(classname, attr.name);
 
                     if (parentType != attr.type) {
-                        throw new CompilationError(sourceElement, attr.name, 
new Throwable(
-                                                       /* (non-Javadoc)
-                                                        * @i18n.test
-                                                        * @org-mes="In class 
'" + p[0] + "' attribute '" + p[1] + "' with type '" + p[2] + "' is overriding 
superclass attribute with same name but different type: " + p[3]
-                                                        */
-                                                       
org.openlaszlo.i18n.LaszloMessages.getMessage(
-                                                           
ViewSchema.class.getName(),"051018-364", new Object[] {classname, attr.name, 
attr.type.toString(), parentType.toString()})
-                                                                               
            ));
+                        env.warn(/* (non-Javadoc)
+                                  * @i18n.test
+                                  * @org-mes="In class '" + p[0] + "' 
attribute '" + p[1] + "' with type '" + p[2] + "' is overriding superclass 
attribute with same name but different type: " + p[3]
+                                  */
+                            org.openlaszlo.i18n.LaszloMessages.getMessage(
+                                ViewSchema.class.getName(),"051018-364", new 
Object[] {classname, attr.name, attr.type.toString(), parentType.toString()}), 
+                            sourceElement);
                     }
                 }
 
+                if (attr.type == ViewSchema.METHOD_TYPE && 
!("true".equals(attr.override))) {
+                    checkMethodDeclaration(sourceElement, classname, 
attr.name, env);
+                }
+
                 // Update the in-memory attribute type table
                 setAttributeType(sourceElement, classname, attr.name, attr);
             }
@@ -446,6 +469,23 @@
         return type;
     }
 
+
+    /**
+     * checks whether a method with a given method is allowed to be overridden
+     * @param elt an Element name
+     * @param methodName a method name
+     * @return boolean if the method exists on the class or superclass
+     */
+    public boolean methodOverrideAllowed(String classname, String methodName)
+    {
+        AttributeSpec methodspec = getClassAttribute(classname, methodName);
+        if (methodspec == null) {
+            return true;
+        } else {
+            return ! ("false".equals(methodspec.override));
+        }
+    }
+
     boolean isMouseEventAttribute(String name) {
         return sMouseEventAttributes.contains(name);
     }
@@ -485,7 +525,7 @@
 
         // This is the base class from which all classes derive unless 
otherwise
         // specified. It has no attributes.
-        makeNewStaticClass("Instance");
+        makeNewStaticClass("Object");
 
         schemaDOM = (Document) sCachedSchemaDOM.clone();
         Element docroot = schemaDOM.getRootElement();

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
        2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
        2007-10-24 03:14:32 UTC (rev 6984)
@@ -80,8 +80,9 @@
     public void testSetAttributes () {
 
         ViewSchema schema = new ViewSchema();
+        CompilationEnvironment env = new CompilationEnvironment();
         try {
-            schema.loadSchema(new CompilationEnvironment());
+            schema.loadSchema(env);
         } catch (JDOMException e) {
             throw new RuntimeException(e.getMessage());
         } catch (IOException e) {
@@ -94,11 +95,11 @@
         Element elt1 = new Element("classdef1");
         Element elt2 = new Element("classdef2");
 
-        schema.addElement(elt1, "mynewclass", "view", new ArrayList());
-        schema.addElement(elt2, "mynewsubclass", "mynewclass", new 
ArrayList());
+        schema.addElement(elt1, "mynewclass", "view", new ArrayList(), env);
+        schema.addElement(elt2, "mynewsubclass", "mynewclass", new 
ArrayList(), env);
 
         assertEquals("undefined class superclass",
-                     null,
+                     "Object",
                      schema.getBaseClassname("view"));
 
         assertEquals(" superclass",
@@ -110,11 +111,11 @@
                      schema.getSuperclassName("mynewsubclass"));
 
         assertEquals("mynewclass superclass",
-                     "view",
+                     "Object",
                      schema.getBaseClassname("mynewclass"));
 
         assertEquals("mynewsubclass superclass",
-                     "view",
+                     "Object",
                      schema.getBaseClassname("mynewsubclass"));
 
 

Modified: 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/xml/internal/Schema.java
===================================================================
--- 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/xml/internal/Schema.java 
    2007-10-24 02:30:16 UTC (rev 6983)
+++ 
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/xml/internal/Schema.java 
    2007-10-24 03:14:32 UTC (rev 6984)
@@ -3,7 +3,7 @@
  * 
****************************************************************************/
 
 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
-* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
+* Copyright 2001-2007 Laszlo Systems, Inc.  All Rights Reserved.              *
 * Use is subject to license terms.                                            *
 * J_LZ_COPYRIGHT_END *********************************************************/
 
@@ -53,6 +53,11 @@
         return newtype;
     }
     
+
+    public static void addTypeAlias(String typeName, Type type) {
+        typeNames.put(typeName, type);
+    }
+
     /** Look up the Type object from a Javascript type name */
     public Type getTypeForName (String typeName) {
         return (Type) typeNames.get(typeName);

Added: openlaszlo/trunk/test/compiler_errors/attribute-overrides-method.lzx


Property changes on: 
openlaszlo/trunk/test/compiler_errors/attribute-overrides-method.lzx
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: openlaszlo/trunk/test/compiler_errors/method-override.lzx


Property changes on: openlaszlo/trunk/test/compiler_errors/method-override.lzx
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: openlaszlo/trunk/test/compiler_errors/override-x-attribute.lzx


Property changes on: 
openlaszlo/trunk/test/compiler_errors/override-x-attribute.lzx
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to