void decompileObjectLiteral(ObjectLiteral node) { decompiler.addToken(Token.LC); List<ObjectProperty> props = node.getElements(); int size = props.size(); for (int i = 0; i < size; i++) { ObjectProperty prop = props.get(i); boolean destructuringShorthand = Boolean.TRUE.equals(prop.getProp(Node.DESTRUCTURING_SHORTHAND)); decompile(prop.getLeft()); if (!destructuringShorthand) { decompiler.addToken(Token.COLON); decompile(prop.getRight()); } if (i < size - 1) { decompiler.addToken(Token.COMMA); } } decompiler.addToken(Token.RC); }
public List<String> getPropertyNames(){ List<String> propNames = new ArrayList<String>(); ObjectLiteral ol = (ObjectLiteral)this.getNode(); for (ObjectProperty op : ol.getElements()){ AstNode left = op.getLeft(); if (left instanceof Name){ propNames.add(((Name)left).getIdentifier()); } else if (left instanceof StringLiteral){ String identifier = ConstraintGenUtil.removeQuotes(((StringLiteral)left).toSource()); propNames.add(identifier); } else { System.err.println(left.getClass().getName() + " " + left.toSource()); throw new Error("unsupported case in getPropertyNames()"); } } return propNames; }
public static List<String> getPropertyNames(ObjectLiteral ol){ List<String> propNames = new ArrayList<String>(); for (ObjectProperty op : ol.getElements()){ AstNode left = op.getLeft(); if (left instanceof Name){ propNames.add(((Name)left).getIdentifier()); } else if (left instanceof StringLiteral){ String identifier = ConstraintGenUtil.removeQuotes(((StringLiteral)left).toSource()); propNames.add(identifier); } else { System.err.println(left.getClass().getName() + " " + left.toSource()); throw new Error("unsupported case in getPropertyNames()"); } } return propNames; }
/** * Create constraints for an object literal. */ private ITypeTerm processObjectLiteralForObject(ObjectLiteral n) { ITypeTerm expTerm = findOrCreateObjectLiteralTerm(n); ObjectLiteral o = (ObjectLiteral)n; for (ObjectProperty prop : o.getElements()){ AstNode left = prop.getLeft(); AstNode right = prop.getRight(); if (left instanceof Name){ String identifier = ((Name)left).getIdentifier(); // for object literal o = { name_1 : exp_1, ..., name_k : exp_k } generate // a constraint |exp_i| <: prop(|o|, name_i) ITypeTerm propTerm = findOrCreatePropertyAccessTerm(expTerm, identifier, null); ITypeTerm valTerm = processExpression(right); processCopy(right, valTerm, propTerm, n.getLineno(), null); } } return expTerm; }
/** * Create constraints for a map literal. */ private ITypeTerm processObjectLiteralForMap(ObjectLiteral o) { ITypeTerm expTerm = findOrCreateMapLiteralTerm(o); for (ObjectProperty prop : o.getElements()){ AstNode left = prop.getLeft(); AstNode right = prop.getRight(); if (left instanceof StringLiteral){ // for map literal o = { name_1 : exp_1, ..., name_k : exp_k } generate // a constraint |exp_i| <: MapElem(|o|) ITypeTerm mapAccessTerm = findOrCreateIndexedTerm(expTerm, o.getLineno()); ITypeTerm valTerm = processExpression(right); processCopy(right, valTerm, mapAccessTerm, o.getLineno(), (solution) -> genericTypeError("map does not have a homogenous value type", locationOf(prop)) .withNote("map value type is " + describeTypeOf(mapAccessTerm, solution)) .withNote("key " + left.toSource() + " has type " + describeTypeOf(valTerm, solution))); } } return expTerm; }
private void visitPrototypeMembers(ObjectLiteral objLiteral, String clazz) { List<ObjectProperty> properties = objLiteral.getElements(); for (ObjectProperty property : properties) { AstNode propertyKey = property.getLeft(); JavaScriptTreeNode tn = createTreeNode(propertyKey); String memberName = RhinoUtil.getPropertyName(propertyKey); AstNode propertyValue = property.getRight(); visitPrototypeMember(tn, clazz, memberName, propertyValue); } }
private ObjectProperty methodDefinition(int pos, AstNode propName, int entryKind) throws IOException { FunctionNode fn = function(FunctionNode.FUNCTION_EXPRESSION); // We've already parsed the function name, so fn should be anonymous. Name name = fn.getFunctionName(); if (name != null && name.length() != 0) { reportError("msg.bad.prop"); } ObjectProperty pn = new ObjectProperty(pos); switch (entryKind) { case GET_ENTRY: pn.setIsGetterMethod(); fn.setFunctionIsGetterMethod(); break; case SET_ENTRY: pn.setIsSetterMethod(); fn.setFunctionIsSetterMethod(); break; case METHOD_ENTRY: pn.setIsNormalMethod(); fn.setFunctionIsNormalMethod(); break; } int end = getNodeEnd(fn); pn.setLeft(propName); pn.setRight(fn); pn.setLength(end - pos); return pn; }
/** * Tests if an object literal is an object by checking that all * properties are unquoted. */ static boolean isObject(ObjectLiteral o){ boolean result = (o.getElements().size() > 0); for (ObjectProperty prop : o.getElements()){ AstNode left = prop.getLeft(); result = result && (left instanceof Name); } return result; }
/** * Tests if an object literal is a map by checking that * all properties are quoted. * In JavaScript, both double quotes and single quotes are * supported but for now we assume double quotes are used. * * Empty object literals are assumed to be maps. */ static boolean isMap(ObjectLiteral o){ boolean result = true; for (ObjectProperty prop : o.getElements()){ AstNode left = prop.getLeft(); result = result && (left instanceof StringLiteral); } return result; }
private void visitMethodOrEnum(final String name, final String jsDoc, final AstNode astNode) { if (jsDoc == null) { //TODO sometimes values are recognized as enums even if they are not. LOG.error("Comment in node {} for file {} is empty.", name, fileName); return; } final JsElement element = parser.parse(fileName, jsDoc); if (element == null || element.isPrivate()) { return; // ignore private stuff... } if (element.isEnum()) { final JsFile jsFile = parseClassOrInterfaceName(name, false, element); files.put(name, jsFile); if (astNode instanceof ObjectLiteral) { final ObjectLiteral ol = (ObjectLiteral) astNode; for (final ObjectProperty op : ol.getElements()) { final Name left = (Name) op.getLeft(); jsFile.addEnumValue(left.toSource(), left.getJsDoc()); } } } else if (isMethod(name, element)) { //method assigned as method variable. final JsMethod method = addMethod(name, element, false); if (method == null) { LOG.warn("Should this be abstract: {} in file:{}", name, fileName); } else { method.setAbstract(true); } } else if (element.isConst() || element.isDefine()){ consts.put(name, element); } else { LOG.warn("We missed something: {}: {} in file:{}", name, element, fileName); } }
private void print(ObjectProperty node) throws IOException { if (node.isGetterMethod()) { writer.append("get "); } else if (node.isSetterMethod()) { writer.append("set "); } Map<String, NameEmitter> oldNameMap = nameMap; nameMap = Collections.emptyMap(); print(node.getLeft()); nameMap = oldNameMap; if (!node.isMethod()) { writer.ws().append(':').ws(); } print(node.getRight()); }
private Node transformObjectLiteral(ObjectLiteral node) { if (node.isDestructuring()) { return node; } // createObjectLiteral rewrites its argument as object // creation plus object property entries, so later compiler // stages don't need to know about object literals. decompiler.addToken(Token.LC); List<ObjectProperty> elems = node.getElements(); Node object = new Node(Token.OBJECTLIT); Object[] properties; if (elems.isEmpty()) { properties = ScriptRuntime.emptyArgs; } else { int size = elems.size(), i = 0; properties = new Object[size]; for (ObjectProperty prop : elems) { if (prop.isGetterMethod()) { decompiler.addToken(Token.GET); } else if (prop.isSetterMethod()) { decompiler.addToken(Token.SET); } else if (prop.isNormalMethod()) { decompiler.addToken(Token.METHOD); } properties[i++] = getPropKey(prop.getLeft()); // OBJECTLIT is used as ':' in object literal for // decompilation to solve spacing ambiguity. if (!(prop.isMethod())) { decompiler.addToken(Token.OBJECTLIT); } Node right = transform(prop.getRight()); if (prop.isGetterMethod()) { right = createUnary(Token.GET, right); } else if (prop.isSetterMethod()) { right = createUnary(Token.SET, right); } else if (prop.isNormalMethod()) { right = createUnary(Token.METHOD, right); } object.addChildToBack(right); if (i < size) { decompiler.addToken(Token.COMMA); } } } decompiler.addToken(Token.RC); object.putProp(Node.OBJECT_IDS_PROP, properties); return object; }
public static boolean isMethodAssignedInObjectLiteral(FunctionNode n){ return (n.getParent() instanceof ObjectProperty && n.getParent().getParent() instanceof ObjectLiteral); }
@Override public boolean visit(AstNode node) { boolean continueProcessing = true; // We only need to check Object Literals if (node instanceof ObjectLiteral) { List<ObjectProperty> kvProps = null; List<ObjectProperty> props = ((ObjectLiteral) node).getElements(); if (props != null) { // Walk through nodes to check if this is a root bundle with // key/value pairs embedded. for (int i = 0; i < props.size(); i++) { Node left = props.get(i).getLeft(); String name = null; if (left instanceof StringLiteral) { name = ((StringLiteral) left).getValue(); } else if (left instanceof Name) { name = ((Name) left).getIdentifier(); } else { continue; } Node right = props.get(i).getRight(); if (name.equalsIgnoreCase("root")) { // This AMD i18n bundle with "root" object // (key/value pairs) embedded. // For example, // // define({ // "root": { // "msg.hello": "Hello", // "msg.byte": "Bye" // }, // "fr": true, // "de": true // }); // right = removeParenthes(right); if (right instanceof ObjectLiteral) { kvProps = ((ObjectLiteral) right).getElements(); break; } } } } if (kvProps == null) { // This bundle contains key/value pairs in the root Object // directly. // For example, // // define({ // "msg.hello": "Hello", // "msg.byte": "Bye" // }); // kvProps = props; } // Put key/value pairs to elements for (ObjectProperty kv : kvProps) { Node propKey = kv.getLeft(); String key = null; if (propKey instanceof Name) { key = ((Name) propKey).getIdentifier(); } else if (propKey instanceof StringLiteral) { key = ((StringLiteral) propKey).getValue(); } if (key == null) { continue; } Node propVal = kv.getRight(); String val = concatStringNodes(propVal); if (val == null) { continue; } elements.put(key, val); } continueProcessing = false; } return continueProcessing; }
/** * It is assumed that <code>descriptorObjectLit</code> has been * identified as an object literal containing property descriptors. Any * property descriptors found as properties of that literal are parsed * and tree nodes are created for them. * * @param descriptorObjLit The object literal containing property * descriptors (for example, the object parameter to * <code>Object.create()</code>). * @param clazz The class that the properties belong to. */ private void visitPropertyDescriptors(ObjectLiteral descriptorObjLit, String clazz) { List<ObjectProperty> descriptors = descriptorObjLit.getElements(); for (ObjectProperty prop : descriptors) { AstNode propertyKey = prop.getLeft(); AstNode propertyValue = prop.getRight(); // Should always be true, as this should be a property descriptor if (propertyValue instanceof ObjectLiteral) { JavaScriptTreeNode tn = createTreeNode(propertyKey); String memberName = RhinoUtil.getPropertyName(propertyKey); visitPropertyDescriptor(tn, clazz, memberName, (ObjectLiteral)propertyValue); } } }