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