http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java ---------------------------------------------------------------------- diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java index aab9712,0000000..4beaf2f mode 100644,000000..100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java @@@ -1,521 -1,0 +1,526 @@@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.js.jx; + +import org.apache.flex.compiler.codegen.ISubEmitter; +import org.apache.flex.compiler.codegen.js.IJSEmitter; +import org.apache.flex.compiler.definitions.IDefinition; +import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens; +import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter; +import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter; +import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens; +import org.apache.flex.compiler.internal.definitions.AccessorDefinition; +import org.apache.flex.compiler.internal.projects.FlexJSProject; +import org.apache.flex.compiler.internal.tree.as.IdentifierNode; +import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode; +import org.apache.flex.compiler.internal.tree.as.UnaryOperatorAtNode; +import org.apache.flex.compiler.projects.ICompilerProject; +import org.apache.flex.compiler.tree.ASTNodeID; +import org.apache.flex.compiler.tree.as.IASNode; +import org.apache.flex.compiler.tree.as.IBinaryOperatorNode; +import org.apache.flex.compiler.tree.as.IClassNode; +import org.apache.flex.compiler.tree.as.IExpressionNode; +import org.apache.flex.compiler.tree.as.IIdentifierNode; +import org.apache.flex.compiler.utils.ASNodeUtils; + +public class BinaryOperatorEmitter extends JSSubEmitter implements + ISubEmitter<IBinaryOperatorNode> +{ + + public BinaryOperatorEmitter(IJSEmitter emitter) + { + super(emitter); + } + + @Override + public void emit(IBinaryOperatorNode node) + { + // TODO (mschmalle) will remove this cast as more things get abstracted + JSFlexJSEmitter fjs = (JSFlexJSEmitter) getEmitter(); + + ASTNodeID id = node.getNodeID(); + /* + if (id == ASTNodeID.Op_InID + || id == ASTNodeID.Op_LogicalAndAssignID + || id == ASTNodeID.Op_LogicalOrAssignID) + { + super.emitBinaryOperator(node); + } + else */if (id == ASTNodeID.Op_IsID || id == ASTNodeID.Op_AsID) + { + fjs.emitIsAs(node, node.getLeftOperandNode(), node.getRightOperandNode(), + id, false); + } + else if (id == ASTNodeID.Op_InstanceOfID) + { + getWalker().walk(node.getLeftOperandNode()); + + startMapping(node, node.getLeftOperandNode()); + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.INSTANCEOF); + endMapping(node); + + IDefinition dnode = (node.getRightOperandNode()) + .resolve(getProject()); + if (dnode != null) + write(getEmitter() + .formatQualifiedName(dnode.getQualifiedName())); + else + getWalker().walk(node.getRightOperandNode()); + } + else + { + IExpressionNode leftSide = node.getLeftOperandNode(); + if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID) + { + IASNode lnode = leftSide.getChild(0); + IASNode rnode = leftSide.getChild(1); + IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ? + ((IIdentifierNode) rnode).resolve(getWalker().getProject()) : + null; + if (lnode.getNodeID() == ASTNodeID.SuperID + && rnodeDef instanceof AccessorDefinition) + { + String op = node.getOperator().getOperatorText(); + boolean isAssignment = op.contains("=") + && !op.contains("==") + && !(op.startsWith("<") || op.startsWith(">") || op + .startsWith("!")); + if (isAssignment) + { + ICompilerProject project = this.getProject(); + if (project instanceof FlexJSProject) + ((FlexJSProject)project).needLanguage = true; + + write(JSFlexJSEmitterTokens.LANGUAGE_QNAME); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSFlexJSEmitterTokens.SUPERSETTER); + write(ASEmitterTokens.PAREN_OPEN); + IClassNode cnode = (IClassNode) node + .getAncestorOfType(IClassNode.class); - write(getEmitter().formatQualifiedName( ++ if (cnode != null) ++ write(getEmitter().formatQualifiedName( + cnode.getQualifiedName())); ++ else ++ write(getEmitter().formatQualifiedName( ++ getModel().getCurrentClass().getQualifiedName())); ++ + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.THIS); + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SINGLE_QUOTE); + write(rnodeDef.getBaseName()); + write(ASEmitterTokens.SINGLE_QUOTE); + writeToken(ASEmitterTokens.COMMA); + + if (op.length() > 1) // += and things like that + { + write(JSFlexJSEmitterTokens.LANGUAGE_QNAME); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSFlexJSEmitterTokens.SUPERSETTER); + write(ASEmitterTokens.PAREN_OPEN); + write(getEmitter().formatQualifiedName( + cnode.getQualifiedName())); + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.THIS); + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SINGLE_QUOTE); + write(rnodeDef.getBaseName()); + write(ASEmitterTokens.SINGLE_QUOTE); + write(ASEmitterTokens.PAREN_CLOSE); + write(op.substring(0, 1)); + } + + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + } + else if (((JSFlexJSEmitter)getEmitter()).isXMLList((MemberAccessExpressionNode)leftSide)) + { + MemberAccessExpressionNode xmlNode = (MemberAccessExpressionNode)leftSide; + if (node.getNodeID() == ASTNodeID.Op_AssignId) + { + getWalker().walk(xmlNode.getLeftOperandNode()); + IExpressionNode rightSide = xmlNode.getRightOperandNode(); + if (rightSide instanceof UnaryOperatorAtNode) + { + write(".setAttribute('"); + getWalker().walk(((UnaryOperatorAtNode)rightSide).getChild(0)); + } + else + { + write(".setChild('"); + getWalker().walk(rightSide); + } + write("', "); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + else if (node.getNodeID() == ASTNodeID.Op_AddAssignID) + { + getWalker().walk(xmlNode); + write(".concat("); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + else if (node.getNodeID() == ASTNodeID.Op_AddID) + { + getWalker().walk(xmlNode); + write(".copy().concat("); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + } + else if (((JSFlexJSEmitter)getEmitter()).isProxy((MemberAccessExpressionNode)leftSide)) + { + MemberAccessExpressionNode proxyNode = (MemberAccessExpressionNode)leftSide; + if (node.getNodeID() == ASTNodeID.Op_AssignId) + { + getWalker().walk(proxyNode.getLeftOperandNode()); + IExpressionNode rightSide = proxyNode.getRightOperandNode(); + write(".setProperty('"); + getWalker().walk(rightSide); + write("', "); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + else if (node.getNodeID() == ASTNodeID.Op_AddAssignID) + { + IExpressionNode rightSide = proxyNode.getRightOperandNode(); + getWalker().walk(proxyNode.getLeftOperandNode()); + write(".setProperty('"); + getWalker().walk(rightSide); + write("', "); + getWalker().walk(proxyNode.getLeftOperandNode()); + write(".getProperty("); + write(ASEmitterTokens.SINGLE_QUOTE); + getWalker().walk(rightSide); + write(ASEmitterTokens.SINGLE_QUOTE); + write(ASEmitterTokens.PAREN_CLOSE); + write(" + "); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + } + else if (((JSFlexJSEmitter)getEmitter()).isDateProperty((MemberAccessExpressionNode)leftSide)) + { + specialCaseDate(node, (MemberAccessExpressionNode)leftSide); + return; + } + } + else if (leftSide.getNodeID() == ASTNodeID.IdentifierID) + { + IDefinition leftDef = leftSide.resolveType(getWalker().getProject()); + if ((leftDef != null) + && IdentifierNode.isXMLish(leftDef, getWalker().getProject())) + { + if (node.getNodeID() == ASTNodeID.Op_AddAssignID) + { + getWalker().walk(leftSide); + write(".concat("); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + return; + } + } + } + + super_emitBinaryOperator(node); + /* + IExpressionNode leftSide = node.getLeftOperandNode(); + + IExpressionNode property = null; + int leftSideChildCount = leftSide.getChildCount(); + if (leftSideChildCount > 0) + { + IASNode childNode = leftSide.getChild(leftSideChildCount - 1); + if (childNode instanceof IExpressionNode) + property = (IExpressionNode) childNode; + else + property = leftSide; + } + else + property = leftSide; + + IDefinition def = null; + if (property instanceof IIdentifierNode) + def = ((IIdentifierNode) property).resolve(getWalker() + .getProject()); + + boolean isSuper = false; + if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID) + { + IASNode cnode = leftSide.getChild(0); + ASTNodeID cId = cnode.getNodeID(); + + isSuper = cId == ASTNodeID.SuperID; + } + + String op = node.getOperator().getOperatorText(); + boolean isAssignment = op.contains("=") && !op.contains("==") && + !(op.startsWith("<") || + op.startsWith(">") || + op.startsWith("!")); + + if (def instanceof AccessorDefinition && isAssignment) + { + // this will make the set_foo call + getWalker().walk(leftSide); + } + else if (isSuper) + { + emitSuperCall(node, ""); + } + else + { + if (ASNodeUtils.hasParenOpen(node)) + write(ASEmitterTokens.PAREN_OPEN); + + getWalker().walk(leftSide); + + if (node.getNodeID() != ASTNodeID.Op_CommaID) + write(ASEmitterTokens.SPACE); + + writeToken(node.getOperator().getOperatorText()); + + getWalker().walk(node.getRightOperandNode()); + + if (ASNodeUtils.hasParenClose(node)) + write(ASEmitterTokens.PAREN_CLOSE); + } + */ + } + } + + private void super_emitBinaryOperator(IBinaryOperatorNode node) + { + if (ASNodeUtils.hasParenOpen(node)) + write(ASEmitterTokens.PAREN_OPEN); + + ASTNodeID id = node.getNodeID(); + + if (id == ASTNodeID.Op_IsID) + { + write(ASEmitterTokens.IS); + write(ASEmitterTokens.PAREN_OPEN); + getWalker().walk(node.getLeftOperandNode()); + writeToken(ASEmitterTokens.COMMA); + getWalker().walk(node.getRightOperandNode()); + write(ASEmitterTokens.PAREN_CLOSE); + } + else if (id == ASTNodeID.Op_AsID) + { + // (is(a, b) ? a : null) + write(ASEmitterTokens.PAREN_OPEN); + write(ASEmitterTokens.IS); + write(ASEmitterTokens.PAREN_OPEN); + getWalker().walk(node.getLeftOperandNode()); + writeToken(ASEmitterTokens.COMMA); + getWalker().walk(node.getRightOperandNode()); + writeToken(ASEmitterTokens.PAREN_CLOSE); + writeToken(ASEmitterTokens.TERNARY); + getWalker().walk(node.getLeftOperandNode()); + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.COLON); + write(ASEmitterTokens.NULL); + write(ASEmitterTokens.PAREN_CLOSE); + } + else + { + getWalker().walk(node.getLeftOperandNode()); + + startMapping(node, node.getLeftOperandNode()); + + if (id != ASTNodeID.Op_CommaID) + write(ASEmitterTokens.SPACE); + + // (erikdebruin) rewrite 'a &&= b' to 'a = a && b' + if (id == ASTNodeID.Op_LogicalAndAssignID + || id == ASTNodeID.Op_LogicalOrAssignID) + { + IIdentifierNode lnode = (IIdentifierNode) node + .getLeftOperandNode(); + + writeToken(ASEmitterTokens.EQUAL); + endMapping(node); + write(lnode.getName()); + + startMapping(node, node.getLeftOperandNode()); + write(ASEmitterTokens.SPACE); + write((id == ASTNodeID.Op_LogicalAndAssignID) ? ASEmitterTokens.LOGICAL_AND + : ASEmitterTokens.LOGICAL_OR); + } + else + { + write(node.getOperator().getOperatorText()); + } + + write(ASEmitterTokens.SPACE); + endMapping(node); + + /* + IDefinition definition = node.getRightOperandNode().resolve(getProject()); + if (definition instanceof FunctionDefinition && + (!(definition instanceof AccessorDefinition))) + { + } + else */ + getWalker().walk(node.getRightOperandNode()); + if (node.getNodeID() == ASTNodeID.Op_InID && + ((JSFlexJSEmitter)getEmitter()).isXML(node.getRightOperandNode())) + { + write(".elementNames()"); + } + else if (node.getNodeID() == ASTNodeID.Op_InID && + ((JSFlexJSEmitter)getEmitter()).isProxy(node.getRightOperandNode())) + { + write(".propertyNames()"); + } + } + + if (ASNodeUtils.hasParenOpen(node)) + write(ASEmitterTokens.PAREN_CLOSE); + } + + private enum DateProperties + { + FULLYEAR("fullYear", "setFullYear"), + MONTH("month", "setMonth"), + DATE("date", "setDate"), + FULLYEARUTC("fullYearUTC", "setUTCFullYear"), + MONTHUTC("monthUTC", "setUTCMonth"), + DATEUTC("dateUTC", "setUTCDate"), + HOURS("hours", "setHours"), + MINUTES("minutes", "setMinutes"), + SECONDS("seconds", "setSeconds"), + MILLISECONDS("milliseconds", "setMilliseconds"), + HOURSUTC("hoursUTC", "setUTCHours"), + MINUTESUTC("minutesUTC", "setUTCMinutes"), + SECONDSUTC("secondsUTC", "setUTCSeconds"), + MILLISECONDSUTC("millisecondsUTC", "setUTCMilliseconds"); + + DateProperties(String value, String functionName) + { + this.value = value; + this.functionName = functionName; + } + + private String value; + private String functionName; + + public String getFunctionName() + { + return functionName; + } + } + + void specialCaseDate(IBinaryOperatorNode node, MemberAccessExpressionNode leftSide) + { + MemberAccessExpressionNode dateNode = (MemberAccessExpressionNode)leftSide; + IIdentifierNode rightSide = (IIdentifierNode)dateNode.getRightOperandNode(); + getWalker().walk(dateNode.getLeftOperandNode()); + String rightName = rightSide.getName(); + DateProperties prop = DateProperties.valueOf(rightName.toUpperCase()); + write(ASEmitterTokens.MEMBER_ACCESS); + write(prop.getFunctionName()); + write(ASEmitterTokens.PAREN_OPEN); + getWalker().walk(node.getRightOperandNode()); + switch (prop) + { + case FULLYEAR: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getMonth()"); + // fall through + case MONTH: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getDate()"); + break; + case FULLYEARUTC: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getMonthUTC()"); + // fall through + case MONTHUTC: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getDateUTC()"); + break; + case HOURS: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getMinutes()"); + // fall through + case MINUTES: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getSeconds()"); + // fall through + case SECONDS: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getMilliseconds()"); + break; + case HOURSUTC: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getUTCMinutes()"); + // fall through + case MINUTESUTC: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getUTCSeconds()"); + // fall through + case SECONDSUTC: + write(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SPACE); + getWalker().walk(dateNode.getLeftOperandNode()); + write(ASEmitterTokens.MEMBER_ACCESS); + write("getUTCMilliseconds()"); + break; + } + write(ASEmitterTokens.PAREN_CLOSE); + } +}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/externals/ExternalsTestUtils.java ---------------------------------------------------------------------- diff --cc compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/externals/ExternalsTestUtils.java index 7956e25,0000000..6eacbde mode 100644,000000..100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/externals/ExternalsTestUtils.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/externals/ExternalsTestUtils.java @@@ -1,173 -1,0 +1,147 @@@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals; + +import java.io.File; +import java.io.IOException; + +import org.apache.flex.compiler.clients.ExternCConfiguration; +import org.apache.flex.utils.FilenameNormalization; + +public class ExternalsTestUtils +{ + public static File TEMP_DIR = new File( + FilenameNormalization.normalize("temp")); + + // XXX missing.js is a temp location until we can figure out where it should placed in the build + public static File MISSING_JS_FILE = FilenameNormalization.normalize(new File( + "../externs/js/missing.js")); + + // XXX AS3.as is a namespace needed to override toString in some classes + public static File AS3_NAMESPACE_FILE = FilenameNormalization.normalize(new File( + "../externs/js/src/AS3.as")); + + public static File EXTERNAL_JS_DIR = FilenameNormalization.normalize(new File( + "../externs/js/externs")); + + public static File EXTERNAL_JQUERY_DIR = FilenameNormalization.normalize(new File( + "../externs/jquery/externs")); + + public static File EXTERNAL_JASMINE_DIR = FilenameNormalization.normalize(new File( + "../externs/jasmine/externs")); + + public static File AS_ROOT_DIR = new File(TEMP_DIR, "externals/as"); + + public static void addTestExcludesFull(ExternCConfiguration config) + { + config.addFieldExclude("Window", "focus"); + config.addClassExclude("controlRange"); + + config.addExclude("Array", "toSource"); + config.addExclude("Date", "valueOf"); + config.addExclude("String", "valueOf"); - - config.addExclude("FontFaceSet", "delete"); - - config.addExclude("CSSStyleDeclaration", "cssText"); - config.addExclude("CSSStyleRule", "style"); - config.addExclude("CSSFontFaceRule", "style"); - config.addExclude("CSSPageRule", "style"); - - config.addExclude("Generator", "throw"); - config.addExclude("Generator", "return"); - config.addExclude("HTMLMenuItemElement", "default"); - config.addExclude("MessageEvent", "data"); // TODO returns T - config.addExclude("MessageEvent", "initMessageEventNS"); // TODO param T - config.addExclude("MessageEvent", "initMessageEvent"); // TODO param T - config.addExclude("MessageEvent", "default"); - config.addExclude("Object", "is"); - config.addExclude("Promise", "catch"); - - config.addExclude("IDBCursor", "continue"); - config.addExclude("IDBCursor", "delete"); - config.addExclude("IDBObjectStore", "delete"); - - // TODO method treated like field - config.addFieldExclude("Iterator", "next"); - config.addExclude("Generator", "next"); - config.addExclude("LinkStyle", "sheet"); + + // SVG + config.addExclude("SVGStylable", "className"); + config.addExclude("SVGStylable", "style"); + config.addExclude("SVGLocatable", "farthestViewportElement"); + config.addExclude("SVGLocatable", "nearestViewportElement"); + + // jQuery XXX (these will need to be defined in some config when we get external libs + // working correctly with EXTERNC) + config.addClassToFunction("$"); + + config.addExclude("jQuery", "is"); + config.addExclude("jQuery", "promise"); + config.addExclude("jQuery", "getJSON"); + config.addExclude("jQuery", "ajax"); + config.addExclude("jQuery", "when"); + config.addExclude("jQuery", "post"); + config.addExclude("jQuery", "getScript"); + config.addExclude("jQuery", "Callbacks"); + + config.addClassExclude("Deferred"); + config.addClassExclude("jQuery.deferred"); + config.addClassExclude("jQuery.Event"); + config.addClassExclude("jQuery.Deferred"); + config.addClassExclude("$.Event"); + config.addClassExclude("$.Deferred"); + config.addClassExclude("$.deferred"); + } + + public static void addTestExternalsFull(ExternCConfiguration config) + throws IOException + { + String coreRoot = ExternalsTestUtils.EXTERNAL_JS_DIR.getAbsolutePath(); + + config.addExternal(ExternalsTestUtils.MISSING_JS_FILE); + config.addExternal(coreRoot + "/es3.js"); + config.addExternal(coreRoot + "/es5.js"); + config.addExternal(coreRoot + "/es6.js"); + + config.addExternal(coreRoot + "/browser/w3c_anim_timing.js"); + config.addExternal(coreRoot + "/browser/w3c_audio.js"); + config.addExternal(coreRoot + "/browser/w3c_batterystatus.js"); + config.addExternal(coreRoot + "/browser/w3c_css.js"); + config.addExternal(coreRoot + "/browser/w3c_css3d.js"); + config.addExternal(coreRoot + "/browser/w3c_device_sensor_event.js"); + config.addExternal(coreRoot + "/browser/w3c_dom1.js"); + config.addExternal(coreRoot + "/browser/w3c_dom2.js"); + config.addExternal(coreRoot + "/browser/w3c_dom3.js"); + config.addExternal(coreRoot + "/browser/w3c_elementtraversal.js"); + config.addExternal(coreRoot + "/browser/w3c_encoding.js"); + config.addExternal(coreRoot + "/browser/w3c_event.js"); + config.addExternal(coreRoot + "/browser/w3c_event3.js"); + config.addExternal(coreRoot + "/browser/w3c_geolocation.js"); + config.addExternal(coreRoot + "/browser/w3c_indexeddb.js"); + config.addExternal(coreRoot + "/browser/w3c_navigation_timing.js"); + config.addExternal(coreRoot + "/browser/w3c_range.js"); + config.addExternal(coreRoot + "/browser/w3c_rtc.js"); + config.addExternal(coreRoot + "/browser/w3c_selectors.js"); + //model.addExternal(coreRoot + "/w3c_serviceworker.js"); + //model.addExternal(coreRoot + "/w3c_webcrypto.js"); + config.addExternal(coreRoot + "/browser/w3c_xml.js"); + + //model.addExternal(coreRoot + "/fetchapi"); + + config.addExternal(coreRoot + "/browser/window.js"); + + config.addExternal(coreRoot + "/browser/ie_dom.js"); + config.addExternal(coreRoot + "/browser/gecko_dom.js"); + + config.addExternal(coreRoot + "/browser/webkit_css.js"); + config.addExternal(coreRoot + "/browser/webkit_dom.js"); + config.addExternal(coreRoot + "/browser/webkit_event.js"); + //model.addExternal(coreRoot + "/webkit_notifications.js"); + + config.addExternal(coreRoot + "/browser/iphone.js"); + config.addExternal(coreRoot + "/browser/chrome.js"); + config.addExternal(coreRoot + "/browser/flash.js"); + + config.addExternal(coreRoot + "/browser/page_visibility.js"); + config.addExternal(coreRoot + "/browser/fileapi.js"); + config.addExternal(coreRoot + "/browser/html5.js"); + + config.addExternal(coreRoot + "/browser/webgl.js"); + config.addExternal(coreRoot + "/browser/webstorage.js"); + + config.addExternal(coreRoot + "/svg.js"); + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler/src/main/java/org/apache/flex/compiler/internal/caches/CSSDocumentCache.java ---------------------------------------------------------------------- diff --cc compiler/src/main/java/org/apache/flex/compiler/internal/caches/CSSDocumentCache.java index be9e03b,0000000..3a8db86 mode 100644,000000..100644 --- a/compiler/src/main/java/org/apache/flex/compiler/internal/caches/CSSDocumentCache.java +++ b/compiler/src/main/java/org/apache/flex/compiler/internal/caches/CSSDocumentCache.java @@@ -1,397 -1,0 +1,400 @@@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.caches; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.zip.ZipFile; + +import org.antlr.runtime.ANTLRFileStream; +import org.antlr.runtime.ANTLRInputStream; +import org.apache.commons.io.IOUtils; + +import org.apache.flex.compiler.config.Configuration; +import org.apache.flex.compiler.css.ICSSDocument; +import org.apache.flex.compiler.css.ICSSFontFace; +import org.apache.flex.compiler.css.ICSSNamespaceDefinition; +import org.apache.flex.compiler.css.ICSSNode; +import org.apache.flex.compiler.css.ICSSRule; +import org.apache.flex.compiler.internal.css.CSSDocument; +import org.apache.flex.compiler.internal.css.CSSModelTreeType; +import org.apache.flex.compiler.problems.ICompilerProblem; +import org.apache.flex.swc.ISWC; +import org.apache.flex.swc.io.SWCReader; +import org.apache.flex.utils.FilenameNormalization; +import com.google.common.collect.ImmutableList; + +/** + * Cache for {@link ICSSDocument} at workspace level. The CSS model can be a + * "defaults.css" file inside a SWC library, or a CSS file on the disk. + * <p> + * The cache key is normalized path to the SWC file (optional) and the CSS file + * name inside the SWC. The cache value is an {@link ICSSDocument}. + */ +public class CSSDocumentCache extends ConcurrentCacheStoreBase<ICSSDocument> +{ + + /** + * Since {@link ConcurrentCacheStoreBase#get} doesn't return compiler + * problems, when there's problem parsing CSS file in + * {@link #createEntryValue}, we have to throw a runtime exception to pass + * the compiler problems to the caller of the cache store. + */ + public static class ProblemParsingCSSRuntimeException extends RuntimeException + { + private static final long serialVersionUID = 156921800741800866L; + + public ProblemParsingCSSRuntimeException(final Collection<ICompilerProblem> problems) + { + super(); + this.cssParserProblems = problems; + } + + /** + * A collection of compiler problems from parsing the CSS file. + */ + public final Collection<ICompilerProblem> cssParserProblems; + } + + /** + * Since {@link ConcurrentCacheStoreBase} does not allow null values, when a + * SWC library does not have a "defaults.css" file, this dummy value is + * used. + */ + public static final ICSSDocument EMPTY_CSS_DOCUMENT = new ICSSDocument() + { + @Override + public ImmutableList<ICSSRule> getRules() + { + return ImmutableList.of(); + } + + @Override + public ICSSNamespaceDefinition getNamespaceDefinition(String prefix) + { + return null; + } + + @Override + public ImmutableList<ICSSFontFace> getFontFaces() + { + return ImmutableList.of(); + } + + @Override + public ICSSNamespaceDefinition getDefaultNamespaceDefinition() + { + return null; + } + + @Override + public ImmutableList<ICSSNamespaceDefinition> getAtNamespaces() + { + return ImmutableList.of(); + } + + @Override + public String toStringTree() + { + return null; + } + + @Override + public int getArity() + { + return 0; + } + + @Override + public ICSSNode getNthChild(int index) + { + throw new IllegalStateException(); + } + + @Override + public CSSModelTreeType getOperator() + { + throw new IllegalStateException(); + } + + @Override + public String getSourcePath() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getStart() + { + return 0; + } + + @Override + public int getEnd() + { + return 0; + } + + @Override + public int getLine() + { + return 0; + } + + @Override + public int getColumn() + { + return 0; + } + + @Override - public int getAbsoluteStart() ++ public int getEndLine() + { + return 0; + } + + @Override - public int getAbsoluteEnd() ++ public int getEndColumn() + { + return 0; + } + + @Override - public int getEndLine() { ++ public int getAbsoluteStart() ++ { + return 0; + } + + @Override - public int getEndColumn() { ++ public int getAbsoluteEnd() ++ { + return 0; + } ++ + }; + + private abstract static class CSSDocumentCacheKeyBase extends CacheStoreKeyBase + { + abstract ICSSDocument parse() throws IOException; + } + + /** + * Key object for {@code CSSDocumentCache}. It the combination of a + * normalized SWC file path and the CSS file inside the SWC. If the + * {@code swcFile} is null, the {@code cssFileName} points to a CSS disk + * file. + */ + public static class CSSDocumentCacheKey extends CSSDocumentCacheKeyBase + { + public final ISWC swc; + public final String cssFileName; + + public CSSDocumentCacheKey(final ISWC swc, final String cssFileName) + { + assert cssFileName != null : "CSS file name can't be null."; + this.swc = swc; + this.cssFileName = cssFileName; + } + + @Override + public String generateKey() + { + return String.format( + "%s:%s", + FilenameNormalization.normalize(swc.getSWCFile()).getAbsolutePath(), + cssFileName); + } + + /** + * Parse a CSS file in a SWC library into {@link ICSSDocument} model. If the + * CSS file does not exist, returns {@link #EMPTY_CSS_DOCUMENT} dummy + * object. + * + * @throws IOException IO error. + */ + @Override + ICSSDocument parse() throws IOException + { + final ZipFile zipFile = new ZipFile(swc.getSWCFile(), ZipFile.OPEN_READ); + ICSSDocument result = EMPTY_CSS_DOCUMENT; + InputStream input = null; + try + { + input = SWCReader.getInputStream(zipFile, cssFileName); + if (input != null) + { + final ANTLRInputStream in = new ANTLRInputStream(input); + in.name = String.format("%s:%s", swc.getSWCFile().getName(), cssFileName); + final List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(); + result = CSSDocument.parse(in, problems); + if (!problems.isEmpty()) + throw new ProblemParsingCSSRuntimeException(problems); + } + } + finally + { + IOUtils.closeQuietly(input); + zipFile.close(); + } + return result; + } + } + + /** + * Key object for {@code CSSDocumentCache}. It the combination of a + * normalized SWC file path and the CSS file inside the SWC. If the + * {@code swcFile} is null, the {@code cssFileName} points to a CSS disk + * file. + */ + protected static class CSSDocumentCacheKey2 extends CSSDocumentCacheKeyBase + { + protected final String cssFileName; // non-null + + public CSSDocumentCacheKey2(final String cssFileName) + { + assert cssFileName != null : "CSS file name can't be null."; + this.cssFileName = cssFileName; + } + + @Override + public String generateKey() + { + return cssFileName; + } + + /** + * parse a bare CSS file on the file system. + */ + @Override + ICSSDocument parse() throws IOException + { + final List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(); + final CSSDocument css = CSSDocument.parse(new ANTLRFileStream(cssFileName), problems); + if (!problems.isEmpty()) + throw new ProblemParsingCSSRuntimeException(problems); + if (css != null) + return css; + return EMPTY_CSS_DOCUMENT; + } + } + + /** + * Create a cache key for {@code CSSDocumentCache} that references + * a CSS file in a SWC. + * + * @param swc SWC file + * @param cssFileName CSS file name + * @return Key for {@code CSSDocumentCache}. + */ + public static CacheStoreKeyBase createKey(final ISWC swc, final String cssFileName) + { + return new CSSDocumentCacheKey(swc, cssFileName); + } + + /** + * Create a cache key for {@code CSSDocumentCache} that references + * a CSS file on disk. + * + * @param cssFileName CSS file name + * @return Key for {@code CSSDocumentCache}. + */ + public static CacheStoreKeyBase createKey(final String cssFileName) + { + return new CSSDocumentCacheKey2(cssFileName); + } + + @Override + protected ICSSDocument createEntryValue(CacheStoreKeyBase key) + { + assert key instanceof CSSDocumentCacheKeyBase : "Expected 'CSSDocumentCacheKeyBase' but got " + key.getClass().getSimpleName(); + final CSSDocumentCacheKeyBase cacheKey = (CSSDocumentCacheKeyBase)key; + + ICSSDocument result = EMPTY_CSS_DOCUMENT; + try + { + result = cacheKey.parse(); + } + catch (IOException e) + { + // Ignore exception and return dummy value. + } + return result; + } + + public static String[] ALL_DEFAULTS_CSS_FILENAMES = {"defaults.css", "defaults-3.0.0.css" }; + + /** + * Get the compatible-mode default CSS filename. + * + * @param version Compatible version. + * @return Defaults CSS filename. + */ + private static String getCompatibleModeCSSFilename(final Integer version) + { + if (version == null) + return "defaults.css"; + else if (version <= Configuration.MXML_VERSION_3_0) + return "defaults-3.0.0.css"; + else + return "defaults.css"; + } + + /** + * Get the "default" CSS model in a SWC library. If + * {@code compatibility-version=3} is set, this method will try to get + * "defaults-3.0.0.css" first. If the compatibility version isn't present, + * it will fall back to "defaults.css". + * + * @param swc SWC file. + * @param compatibilityVersion Compatibility version, or null if the + * compiler is not under compatibility mode. + * @return "defaults" CSS model or null if not found + */ + public ICSSDocument getDefaultsCSS(final ISWC swc, final Integer compatibilityVersion) + { + final CacheStoreKeyBase key; + final String cssFilename = getCompatibleModeCSSFilename(compatibilityVersion); + key = createKey(swc, cssFilename); + + final ICSSDocument css = this.get(key); + assert css != null : "ConcurrentCacheStoreBase never caches null value."; + + if (css == CSSDocumentCache.EMPTY_CSS_DOCUMENT) + { + if (compatibilityVersion != null) + { + // If compatible CSS is not present, fall back to "defaults.css". + return getDefaultsCSS(swc, null); + } + else + { + return null; + } + } + else + { + return css; + } + } +}
