protected void parseNode(Node node) { switch (node.getType()) { // Function call token case Token.CALL: if (isDojoCall(node)) { // We are looking for dojo.some_function(...) calls, this means first // child of function call is property resolution of function in the // dojo object. Node propertyResolution = node.getFirstChild(); if (propertyResolution != null) { // Find property label accessing object String propertyName = functionPropertyName(propertyResolution); // Single argument module functions, put out value and store in appropriate list. if ("require".equals(propertyName) || "provide".equals(propertyName) || "declare".equals(propertyName)) { String firstArg = functionCallArgument(propertyResolution, 0); List<String> moduleList = moduleLists.get(propertyName); if (!moduleList.contains(firstArg)) { moduleList.add(firstArg); } } else if ("registerModulePath".equals(propertyName)) { // Extract module identifier and module path, first two arguments to // dojo.registerModulePath(); String modulePrefix = functionCallArgument(propertyResolution, 0); String modulePath = functionCallArgument(propertyResolution, 1); modulePaths.put(modulePrefix, modulePath); } } } break; // Global identifier token, check for djConfig assignment, djConfig = {...} case Token.SETNAME: // LHS is global name binding. Node bindName = node.getFirstChild(); // LHS should be djConfig global assignment. if (bindName.getType() == Token.BINDNAME && "djConfig".equals(bindName.getString())) { // RHS of statement should be literal assignment. Node assignmentExpr = node.getLastChild(); parseModulePathsExpr(assignmentExpr); } break; // Local identifier token, check for djConfig assignment, var djConfig = {...} case Token.NAME: // LHS is name token if ("djConfig".equals(node.getString())) { // Check for object literal assignment Node assignmentExpr = node.getFirstChild(); parseModulePathsExpr(assignmentExpr); } break; } }
protected Map<String, String> findLiteralStringValues(Node objLiteral) { Map<String, String> literalValues = new HashMap<String, String>(); // Find object literal keys from property list. Object[] propertyList = (Object[]) objLiteral.getProp(Token.EQ); // Iterate through each literal key, extracting associated value. Ignore // any non-string values, we aren't attempting inner-resolution of references. if (propertyList != null) { int numArgs = 0; // Child nodes are linked list of object values Node propertyValue = objLiteral.getFirstChild(); while (numArgs < propertyList.length) { // Convert key/value pairs into a handy format if (propertyValue.getType() == Token.STRING) { literalValues.put((String) propertyList[numArgs], propertyValue.getString()); } propertyValue = propertyValue.getNext(); numArgs++; } } return literalValues; }
// Given child nodes for a function call, object ref and arguments, return // the string value for the first argument. Ignore any complicated resolution. protected String functionCallArgument(Node functionCallNodes, int argIndex) { String fnCallArg = null; // Traverse argument nodes until we reach desired one. Node argument = functionCallNodes.getNext(); while (argument != null && argIndex > 0) { argument = argument.getNext(); argIndex--; } ; // Check we have a simple type value. if (argument != null && argument.getType() == Token.STRING) { fnCallArg = argument.getString(); } return fnCallArg; }
// Extract property name accessed. Will have two child nodes, // object reference and property name. Ignore any further // variable resolution. protected String functionPropertyName(Node propertyLookup) { String propertyName = null; // First argument is an object reference that lookup should be // performed against. Node objectReference = propertyLookup.getFirstChild(); if (objectReference != null) { // Find property identifier we are retrieving... Node propertyNameNode = objectReference.getNext(); // Only handle explicit string properties, we cannot resolve variables. if (propertyNameNode != null && propertyNameNode.getType() == Token.STRING) { propertyName = propertyNameNode.getString(); } } return propertyName; }