Java Code Examples for com.google.javascript.rhino.Node#addChildToFront()

The following examples show how to use com.google.javascript.rhino.Node#addChildToFront() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: 1_JsDocInfoParser.java    From SimFix with GNU General Public License v2.0 6 votes vote down vote up
/**
 * TypeName := NameExpression | NameExpression TypeApplication
 * TypeApplication := '.<' TypeExpressionList '>'
 * TypeExpressionList := TypeExpression // a white lie
 */
private Node parseTypeName(JsDocToken token) {
  if (token != JsDocToken.STRING) {
    return reportGenericTypeSyntaxWarning();
  }

  Node typeName = newStringNode(stream.getString());
  if (match(JsDocToken.LT)) {
    next();
    skipEOLs();
    Node memberType = parseTypeExpressionList(next());
    if (memberType != null) {
      typeName.addChildToFront(memberType);

      skipEOLs();
      if (!match(JsDocToken.GT)) {
        return reportTypeSyntaxWarning("msg.jsdoc.missing.gt");
      }

      next();
    }
  }
  return typeName;
}
 
Example 2
Source File: AstParallelizer.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void split(Node n) {
  Node c = n.getFirstChild();
  Node before = null;
  while (c != null) {
    Node next = c.getNext();
    if (shouldSplit.apply(c)) {
      Node placeHolder = placeHolderProvider.get();
      if (before == null) {
        forest.add(n.removeFirstChild());
        n.addChildToFront(placeHolder);
      } else {
        n.addChildAfter(placeHolder, c);
        n.removeChildAfter(before);
        forest.add(c);
      }
      recordSplitPoint(placeHolder, before, c);
      before = placeHolder;
    } else {
      split(c);
      before = c;
    }
    c = next;
  }
}
 
Example 3
Source File: Closure_79_Normalize_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Rewrite the function declaration from:
 *   function x() {}
 *   FUNCTION
 *     NAME
 *     LP
 *     BLOCK
 * to:
 *   var x = function() {};
 *   VAR
 *     NAME
 *       FUNCTION
 *         NAME (w/ empty string)
 *         LP
 *         BLOCK
 */
private void rewriteFunctionDeclaration(Node n) {
  // Prepare a spot for the function.
  Node oldNameNode = n.getFirstChild();
  Node fnNameNode = oldNameNode.cloneNode();
  Node var = new Node(Token.VAR, fnNameNode, n.getLineno(), n.getCharno());
  var.copyInformationFrom(n);

  // Prepare the function
  oldNameNode.setString("");

  // Move the function
  Node parent = n.getParent();
  parent.replaceChild(n, var);
  fnNameNode.addChildToFront(n);

  reportCodeChange("Function declaration");
}
 
Example 4
Source File: jKali_003_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Given a node tree, finds all the VAR declarations in that tree that are
 * not in an inner scope. Then adds a new VAR node at the top of the current
 * scope that redeclares them, if necessary.
 */
static void redeclareVarsInsideBranch(Node branch) {
  Collection<Node> vars = getVarsDeclaredInBranch(branch);
  if (vars.isEmpty()) {
    return;
  }

  Node parent = getAddingRoot(branch);
  for (Node nameNode : vars) {
    Node var = IR.var(
        IR.name(nameNode.getString())
            .srcref(nameNode))
        .srcref(nameNode);
    copyNameAnnotations(nameNode, var.getFirstChild());
    parent.addChildToFront(var);
  }
}
 
Example 5
Source File: Closure_79_Normalize_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Rewrite the function declaration from:
 *   function x() {}
 *   FUNCTION
 *     NAME
 *     LP
 *     BLOCK
 * to:
 *   var x = function() {};
 *   VAR
 *     NAME
 *       FUNCTION
 *         NAME (w/ empty string)
 *         LP
 *         BLOCK
 */
private void rewriteFunctionDeclaration(Node n) {
  // Prepare a spot for the function.
  Node oldNameNode = n.getFirstChild();
  Node fnNameNode = oldNameNode.cloneNode();
  Node var = new Node(Token.VAR, fnNameNode, n.getLineno(), n.getCharno());
  var.copyInformationFrom(n);

  // Prepare the function
  oldNameNode.setString("");

  // Move the function
  Node parent = n.getParent();
  parent.replaceChild(n, var);
  fnNameNode.addChildToFront(n);

  reportCodeChange("Function declaration");
}
 
Example 6
Source File: Closure_113_ProcessClosurePrimitives_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Creates a simple namespace variable declaration
 * (e.g. <code>var foo = {};</code>).
 */
private Node makeVarDeclNode() {
  Node name = IR.name(namespace);
  name.addChildToFront(createNamespaceLiteral());

  Node decl = IR.var(name);
  decl.putBooleanProp(Node.IS_NAMESPACE, true);

  // TODO(nicksantos): ew ew ew. Create a mutator package.
  if (compiler.getCodingConvention().isConstant(namespace)) {
    name.putBooleanProp(Node.IS_CONSTANT_NAME, true);
  }
  if (candidateDefinition == null) {
    name.setJSDocInfo(createConstantJsDoc());
  }

  Preconditions.checkState(isNamespacePlaceholder(decl));
  setSourceInfo(decl);
  return decl;
}
 
Example 7
Source File: ProcessCommonJSModules.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Visit require calls. Emit corresponding goog.require and rewrite require
 * to be a direct reference to name of require module.
 */
private void visitRequireCall(NodeTraversal t, Node require, Node parent) {
  String moduleName = toModuleName(require.getChildAtIndex(1).getString(),
      normalizeSourceName(t.getSourceName()));
  Node moduleRef = IR.name(moduleName).srcref(require);
  parent.replaceChild(require, moduleRef);
  Node script = getCurrentScriptNode(parent);
  if (reportDependencies) {
    t.getInput().addRequire(moduleName);
  }
  // Rewrite require("name").
  script.addChildToFront(IR.exprResult(
      IR.call(IR.getprop(IR.name("goog"), IR.string("require")),
          IR.string(moduleName))).copyInformationFromForTree(require));
  compiler.reportCodeChange();
}
 
Example 8
Source File: Closure_79_Normalize_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * @param after The child node to insert the newChild after, or null if
 *     newChild should be added to the front of parent's child list.
 * @return The inserted child node.
 */
private Node addToFront(Node parent, Node newChild, Node after) {
  if (after == null) {
    parent.addChildToFront(newChild);
  } else {
    parent.addChildAfter(newChild, after);
  }
  return newChild;
}
 
Example 9
Source File: Closure_81_IRFactory_t.java    From coming with MIT License 5 votes vote down vote up
@Override
Node processObjectLiteral(ObjectLiteral literalNode) {
  if (literalNode.isDestructuring()) {
    reportDestructuringAssign(literalNode);
  }

  Node node = newNode(Token.OBJECTLIT);
  for (ObjectProperty el : literalNode.getElements()) {
    if (!config.acceptES5) {
      if (el.isGetter()) {
        reportGetter(el);
        continue;
      } else if (el.isSetter()) {
        reportSetter(el);
        continue;
      }
    }

    Node key = transformAsString(el.getLeft());
    Node value = transform(el.getRight());
    if (el.isGetter()) {
      key.setType(Token.GET);
      Preconditions.checkState(value.getType() == Token.FUNCTION);
      if (getFnParamNode(value).hasChildren()) {
        reportGetterParam(el.getLeft());
      }
    } else if (el.isSetter()) {
      key.setType(Token.SET);
      Preconditions.checkState(value.getType() == Token.FUNCTION);
      if (!getFnParamNode(value).hasOneChild()) {
        reportSetterParam(el.getLeft());
      }
    }
    key.addChildToFront(value);
    node.addChildToBack(key);
  }
  return node;
}
 
Example 10
Source File: Nopol2017_0019_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Move all the child nodes following start in srcParent to the end of
 * destParent's child list.
 * @param start The start point in the srcParent child list.
 * @param srcParent The parent node of start.
 * @param destParent The destination node.
 */
private static void moveAllFollowing(
    Node start, Node srcParent, Node destParent) {
  for (Node n = start.getNext(); n != null; n = start.getNext()) {
    boolean isFunctionDeclaration = NodeUtil.isFunctionDeclaration(n);
    srcParent.removeChild(n);
    if (isFunctionDeclaration) {
      destParent.addChildToFront(n);
    } else {
      destParent.addChildToBack(n);
    }
  }
}
 
Example 11
Source File: Closure_26_ProcessCommonJSModules_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Emit goog.provide and add suffix to all global vars to avoid conflicts
 * with other modules.
 */
private void visitScript(NodeTraversal t, Node script) {
  Preconditions.checkArgument(scriptNodeCount == 1,
      "ProcessCommonJSModules supports only one invocation per " +
      "CompilerInput / script node");
  String moduleName = guessCJSModuleName(normalizeSourceName(script
      .getSourceFileName()));
  script.addChildToFront(IR.var(IR.name(moduleName), IR.objectlit())
      .copyInformationFromForTree(script));
  if (reportDependencies) {
    CompilerInput ci = t.getInput();
    ci.addProvide(moduleName);
    JSModule m = new JSModule(moduleName);
    m.addAndOverrideModule(ci);
    module = m;
  }
  script.addChildToFront(IR.exprResult(
      IR.call(IR.getprop(IR.name("goog"), IR.string("provide")),
          IR.string(moduleName))).copyInformationFromForTree(script));

  emitOptionalModuleExportsOverride(script, moduleName);

  // Rename vars to not conflict in global scope.
  NodeTraversal.traverse(compiler, script, new SuffixVarsCallback(
      moduleName));

  compiler.reportCodeChange();
}
 
Example 12
Source File: Closure_32_JsDocInfoParser_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * TypeName := NameExpression | NameExpression TypeApplication
 * TypeApplication := '.<' TypeExpressionList '>'
 * TypeExpressionList := TypeExpression // a white lie
 */
private Node parseTypeName(JsDocToken token) {
  if (token != JsDocToken.STRING) {
    return reportGenericTypeSyntaxWarning();
  }

  String typeName = stream.getString();
  int lineno = stream.getLineno();
  int charno = stream.getCharno();
  while (match(JsDocToken.EOL) &&
      typeName.charAt(typeName.length() - 1) == '.') {
    skipEOLs();
    if (match(JsDocToken.STRING)) {
      next();
      typeName += stream.getString();
    }
  }

  Node typeNameNode = newStringNode(typeName, lineno, charno);

  if (match(JsDocToken.LT)) {
    next();
    skipEOLs();
    Node memberType = parseTypeExpressionList(next());
    if (memberType != null) {
      typeNameNode.addChildToFront(memberType);

      skipEOLs();
      if (!match(JsDocToken.GT)) {
        return reportTypeSyntaxWarning("msg.jsdoc.missing.gt");
      }

      next();
    }
  }
  return typeNameNode;
}
 
Example 13
Source File: Closure_32_JsDocInfoParser_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * TypeName := NameExpression | NameExpression TypeApplication
 * TypeApplication := '.<' TypeExpressionList '>'
 * TypeExpressionList := TypeExpression // a white lie
 */
private Node parseTypeName(JsDocToken token) {
  if (token != JsDocToken.STRING) {
    return reportGenericTypeSyntaxWarning();
  }

  String typeName = stream.getString();
  int lineno = stream.getLineno();
  int charno = stream.getCharno();
  while (match(JsDocToken.EOL) &&
      typeName.charAt(typeName.length() - 1) == '.') {
    skipEOLs();
    if (match(JsDocToken.STRING)) {
      next();
      typeName += stream.getString();
    }
  }

  Node typeNameNode = newStringNode(typeName, lineno, charno);

  if (match(JsDocToken.LT)) {
    next();
    skipEOLs();
    Node memberType = parseTypeExpressionList(next());
    if (memberType != null) {
      typeNameNode.addChildToFront(memberType);

      skipEOLs();
      if (!match(JsDocToken.GT)) {
        return reportTypeSyntaxWarning("msg.jsdoc.missing.gt");
      }

      next();
    }
  }
  return typeNameNode;
}
 
Example 14
Source File: Closure_126_MinimizeExitPoints_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Move all the child nodes following start in srcParent to the end of
 * destParent's child list.
 * @param start The start point in the srcParent child list.
 * @param srcParent The parent node of start.
 * @param destParent The destination node.
 */
private static void moveAllFollowing(
    Node start, Node srcParent, Node destParent) {
  for (Node n = start.getNext(); n != null; n = start.getNext()) {
    boolean isFunctionDeclaration = NodeUtil.isFunctionDeclaration(n);
    srcParent.removeChild(n);
    if (isFunctionDeclaration) {
      destParent.addChildToFront(n);
    } else {
      destParent.addChildToBack(n);
    }
  }
}
 
Example 15
Source File: Closure_130_CollapseProperties_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Updates the first initialization (a.k.a "declaration") of a global name
 * that occurs at an ASSIGN node. See comment for
 * {@link #updateObjLitOrFunctionDeclaration}.
 *
 * @param n An object representing a global name (e.g. "a", "a.b.c")
 * @param alias The flattened name for {@code n} (e.g. "a", "a$b$c")
 */
private void updateObjLitOrFunctionDeclarationAtAssignNode(
    Name n, String alias, boolean canCollapseChildNames) {
  // NOTE: It's important that we don't add additional nodes
  // (e.g. a var node before the exprstmt) because the exprstmt might be
  // the child of an if statement that's not inside a block).

  Ref ref = n.getDeclaration();
  Node rvalue = ref.node.getNext();
  Node varNode = new Node(Token.VAR);
  Node varParent = ref.node.getAncestor(3);
  Node gramps = ref.node.getAncestor(2);
  boolean isObjLit = rvalue.isObjectLit();
  boolean insertedVarNode = false;

  if (isObjLit && n.canEliminate()) {
    // Eliminate the object literal altogether.
    varParent.replaceChild(gramps, varNode);
    ref.node = null;
    insertedVarNode = true;

  } else if (!n.isSimpleName()) {
    // Create a VAR node to declare the name.
    if (rvalue.isFunction()) {
      checkForHosedThisReferences(rvalue, n.docInfo, n);
    }

    ref.node.getParent().removeChild(rvalue);

    Node nameNode = NodeUtil.newName(
        compiler.getCodingConvention(),
        alias, ref.node.getAncestor(2), n.getFullName());

    JSDocInfo info = ref.node.getParent().getJSDocInfo();
    if (ref.node.getLastChild().getBooleanProp(Node.IS_CONSTANT_NAME) ||
        (info != null && info.isConstant())) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
    }

    if (info != null) {
      varNode.setJSDocInfo(info);
    }
    varNode.addChildToBack(nameNode);
    nameNode.addChildToFront(rvalue);
    varParent.replaceChild(gramps, varNode);

    // Update the node ancestry stored in the reference.
    ref.node = nameNode;
    insertedVarNode = true;
  }

  if (canCollapseChildNames) {
    if (isObjLit) {
      declareVarsForObjLitValues(
          n, alias, rvalue,
          varNode, varParent.getChildBefore(varNode), varParent);
    }

    addStubsForUndeclaredProperties(n, alias, varParent, varNode);
  }

  if (insertedVarNode) {
    if (!varNode.hasChildren()) {
      varParent.removeChild(varNode);
    }
    compiler.reportCodeChange();
  }
}
 
Example 16
Source File: Closure_90_FunctionType_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public JSType getPropertyType(String name) {
  if ("prototype".equals(name)) {
    return getPrototype();
  } else {
    if (!hasOwnProperty(name)) {
      if ("call".equals(name)) {
        // Define the "call" function lazily.
        Node params = getParametersNode();
        if (params == null) {
          // If there's no params array, don't do any type-checking
          // in this CALL function.
          defineDeclaredProperty(name,
              new FunctionBuilder(registry)
                  .withReturnType(getReturnType())
                  .build(),
              false);
        } else {
          params = params.cloneTree();
          Node thisTypeNode = Node.newString(Token.NAME, "thisType");
          thisTypeNode.setJSType(
              registry.createOptionalNullableType(getTypeOfThis()));
          params.addChildToFront(thisTypeNode);
          thisTypeNode.setOptionalArg(true);

          defineDeclaredProperty(name,
              new FunctionBuilder(registry)
                  .withParamsNode(params)
                  .withReturnType(getReturnType())
                  .build(),
              false);
        }
      } else if ("apply".equals(name)) {
        // Define the "apply" function lazily.
        FunctionParamBuilder builder = new FunctionParamBuilder(registry);

        // Ecma-262 says that apply's second argument must be an Array
        // or an arguments object. We don't model the arguments object,
        // so let's just be forgiving for now.
        // TODO(nicksantos): Model the Arguments object.
        builder.addOptionalParams(
            registry.createNullableType(getTypeOfThis()),
            registry.createNullableType(
                registry.getNativeType(JSTypeNative.OBJECT_TYPE)));

        defineDeclaredProperty(name,
            new FunctionBuilder(registry)
                .withParams(builder)
                .withReturnType(getReturnType())
                .build(),
            false);
      }
    }

    return super.getPropertyType(name);
  }
}
 
Example 17
Source File: Closure_54_FunctionType_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public JSType getPropertyType(String name) {
  if (!hasOwnProperty(name)) {
    if ("call".equals(name)) {
      // Define the "call" function lazily.
      Node params = getParametersNode();
      if (params == null) {
        // If there's no params array, don't do any type-checking
        // in this CALL function.
        defineDeclaredProperty(name,
            new FunctionBuilder(registry)
            .withReturnType(getReturnType())
            .build(),
            source);
      } else {
        params = params.cloneTree();
        Node thisTypeNode = Node.newString(Token.NAME, "thisType");
        thisTypeNode.setJSType(
            registry.createOptionalNullableType(getTypeOfThis()));
        params.addChildToFront(thisTypeNode);
        thisTypeNode.setOptionalArg(true);

        defineDeclaredProperty(name,
            new FunctionBuilder(registry)
            .withParamsNode(params)
            .withReturnType(getReturnType())
            .build(),
            source);
      }
    } else if ("apply".equals(name)) {
      // Define the "apply" function lazily.
      FunctionParamBuilder builder = new FunctionParamBuilder(registry);

      // Ecma-262 says that apply's second argument must be an Array
      // or an arguments object. We don't model the arguments object,
      // so let's just be forgiving for now.
      // TODO(nicksantos): Model the Arguments object.
      builder.addOptionalParams(
          registry.createNullableType(getTypeOfThis()),
          registry.createNullableType(
              registry.getNativeType(JSTypeNative.OBJECT_TYPE)));

      defineDeclaredProperty(name,
          new FunctionBuilder(registry)
          .withParams(builder)
          .withReturnType(getReturnType())
          .build(),
          source);
    }
  }

  return super.getPropertyType(name);
}
 
Example 18
Source File: ProcessClosurePrimitives.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Replace the provide statement.
 *
 * If we're providing a name with no definition, then create one.
 * If we're providing a name with a duplicate definition, then make sure
 * that definition becomes a declaration.
 */
void replace() {
  if (firstNode == null) {
    // Don't touch the base case ('goog').
    replacementNode = candidateDefinition;
    return;
  }

  // Handle the case where there is a duplicate definition for an explicitly
  // provided symbol.
  if (candidateDefinition != null && explicitNode != null) {
    explicitNode.detachFromParent();
    compiler.reportCodeChange();

    // Does this need a VAR keyword?
    replacementNode = candidateDefinition;
    if (candidateDefinition.isExprResult() &&
        !candidateDefinition.getFirstChild().isQualifiedName()) {
      candidateDefinition.putBooleanProp(Node.IS_NAMESPACE, true);
      Node assignNode = candidateDefinition.getFirstChild();
      Node nameNode = assignNode.getFirstChild();
      if (nameNode.isName()) {
        // Need to convert this assign to a var declaration.
        Node valueNode = nameNode.getNext();
        assignNode.removeChild(nameNode);
        assignNode.removeChild(valueNode);
        nameNode.addChildToFront(valueNode);
        Node varNode = IR.var(nameNode);
        varNode.copyInformationFrom(candidateDefinition);
        candidateDefinition.getParent().replaceChild(
            candidateDefinition, varNode);
        nameNode.setJSDocInfo(assignNode.getJSDocInfo());
        compiler.reportCodeChange();
        replacementNode = varNode;
      }
    }
  } else {
    // Handle the case where there's not a duplicate definition.
    replacementNode = createDeclarationNode();
    if (firstModule == minimumModule) {
      firstNode.getParent().addChildBefore(replacementNode, firstNode);
    } else {
      // In this case, the name was implicitly provided by two independent
      // modules. We need to move this code up to a common module.
      int indexOfDot = namespace.lastIndexOf('.');
      if (indexOfDot == -1) {
        // Any old place is fine.
        compiler.getNodeForCodeInsertion(minimumModule)
            .addChildToBack(replacementNode);
      } else {
        // Add it after the parent namespace.
        ProvidedName parentName =
            providedNames.get(namespace.substring(0, indexOfDot));
        Preconditions.checkNotNull(parentName);
        Preconditions.checkNotNull(parentName.replacementNode);
        parentName.replacementNode.getParent().addChildAfter(
            replacementNode, parentName.replacementNode);
      }
    }
    if (explicitNode != null) {
      explicitNode.detachFromParent();
    }
    compiler.reportCodeChange();
  }
}
 
Example 19
Source File: Closure_72_FunctionToBlockMutator_s.java    From coming with MIT License 4 votes vote down vote up
/**
 *  Convert returns to assignments and breaks, as needed.
 *  For example, with a lableName of 'foo':
 *    {
 *      return a;
 *    }
 *  becomes:
 *    foo: {
 *      a;
 *      break foo;
 *    }
 *  or
 *    foo: {
 *      resultName = a;
 *      break foo;
 *    }
 *
 * @param resultMustBeSet Whether the result must always be set to a value.
 * @return The node containing the transformed block, this may be different
 *     than the passed in node 'block'.
 */
private static Node replaceReturns(
    Node block, String resultName, String labelName,
    boolean resultMustBeSet) {
  Preconditions.checkNotNull(block);
  Preconditions.checkNotNull(labelName);

  Node root = block;

  boolean hasReturnAtExit = false;
  int returnCount = NodeUtil.getNodeTypeReferenceCount(
      block, Token.RETURN, new NodeUtil.MatchShallowStatement());
  if (returnCount > 0) {
    hasReturnAtExit = hasReturnAtExit(block);
    // TODO(johnlenz): Simpler not to special case this,
    // and let it be optimized later.
    if (hasReturnAtExit) {
      convertLastReturnToStatement(block, resultName);
      returnCount--;
    }

    if (returnCount > 0) {
      // A label and breaks are needed.

      // Add the breaks
      replaceReturnWithBreak(block, null, resultName, labelName);

      // Add label
      Node label = new Node(Token.LABEL).copyInformationFrom(block);
      Node name = Node.newString(Token.LABEL_NAME, labelName)
          .copyInformationFrom(block);
      label.addChildToFront(name);
      label.addChildToBack(block);

      Node newRoot = new Node(Token.BLOCK).copyInformationFrom(block);
      newRoot.addChildrenToBack(label);


      // The label is now the root.
      root = newRoot;
    }
  }

  // If there wasn't an return at the end of the function block, and we need
  // a result, add one to the block.
  if (resultMustBeSet && !hasReturnAtExit && resultName != null) {
    addDummyAssignment(block, resultName);
  }

  return root;
}
 
Example 20
Source File: Closure_89_CollapseProperties_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Updates the first initialization (a.k.a "declaration") of a global name
 * that occurs at an ASSIGN node. See comment for
 * {@link #updateObjLitOrFunctionDeclaration}.
 *
 * @param n An object representing a global name (e.g. "a", "a.b.c")
 * @param alias The flattened name for {@code n} (e.g. "a", "a$b$c")
 */
private void updateObjLitOrFunctionDeclarationAtAssignNode(
    Name n, String alias) {
  // NOTE: It's important that we don't add additional nodes
  // (e.g. a var node before the exprstmt) because the exprstmt might be
  // the child of an if statement that's not inside a block).

  Ref ref = n.declaration;
  Node rvalue = ref.node.getNext();
  Node varNode = new Node(Token.VAR);
  Node varParent = ref.node.getAncestor(3);
  Node gramps = ref.node.getAncestor(2);
  boolean isObjLit = rvalue.getType() == Token.OBJECTLIT;

  if (isObjLit && n.canEliminate()) {
    // Eliminate the object literal altogether.
    varParent.replaceChild(gramps, varNode);
    ref.node = null;

  } else {
    if (rvalue.getType() == Token.FUNCTION) {
      checkForHosedThisReferences(rvalue, n.docInfo, n);
    }

    ref.node.getParent().removeChild(rvalue);

    Node nameNode = NodeUtil.newName(
        compiler.getCodingConvention(),
        alias, ref.node.getAncestor(2), n.fullName());

    if (ref.node.getLastChild().getBooleanProp(Node.IS_CONSTANT_NAME)) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
    }

    varNode.addChildToBack(nameNode);
    nameNode.addChildToFront(rvalue);
    varParent.replaceChild(gramps, varNode);

    // Update the node ancestry stored in the reference.
    ref.node = nameNode;
  }

  if (isObjLit) {
    declareVarsForObjLitValues(
        n, alias, rvalue,
        varNode, varParent.getChildBefore(varNode), varParent);
  }

  addStubsForUndeclaredProperties(n, alias, varParent, varNode);

  if (!varNode.hasChildren()) {
    varParent.removeChild(varNode);
  }

  compiler.reportCodeChange();
}