Package com.google.caja.parser.js

Examples of com.google.caja.parser.js.Identifier


      int nUses = v.uses.size();
      if (canonLen * nUses > 8 + canonLen + 2 * nUses + requiredSavings) {
        // TODO(mikesamuel): choose a guaranteed non-interfering name.
        String name = "$_$__litpool__" + decls.size() + "$_$";
        decls.add(new Declaration(
            pos, new Identifier(pos, name), v.uses.get(0).node));
        for (AncestorChain<Literal> use : v.uses) {
          Reference ref = new Reference(
              new Identifier(use.node.getFilePosition(), name));
          use.parent.cast(MutableParseTreeNode.class).node
              .replaceChild(ref, use.node);
        }
      }
    }
View Full Code Here


      values.add(new IntegerLiteral(unk, valueMaker.apply(e)));
    }
    return new ExpressionStmt(unk,
        (Expression) QuasiBuilder.substV(
            "html4.@i = { @k*: @v* };",
            "i", new Reference(new Identifier(unk, key)),
            "k", new ParseTreeNodeContainer(keys),
            "v", new ParseTreeNodeContainer(values)));
  }
View Full Code Here

  private int longestKeyLength = 0;

  private static final FilePosition UNK = FilePosition.UNKNOWN;

  public ParseTreeKB() {
    addFactInt(new Reference(new Identifier(UNK, "undefined")), Fact.UNDEFINED);
    addFactInt(new Reference(new Identifier(UNK, "this")), Fact.GLOBAL);
  }
View Full Code Here

  }

  private static Expression withTopRef(Expression e, String lhs) {
    if (e instanceof Reference) {
      return Operation.createInfix(
          Operator.MEMBER_ACCESS, new Reference(new Identifier(UNK, lhs)), e);
    } else {
      Operation op = (Operation) e;
      List<? extends Expression> operands = op.children();
      return Operation.create(
          e.getFilePosition(), op.getOperator(),
View Full Code Here

                throw new SomethingWidgyHappenedError(
                    "Local variable unexpectedly not set", ex);
              }
              headDecls.add((Declaration) QuasiBuilder.substV(
                  "var @newName = this",
                  "newName", new Identifier(FilePosition.UNKNOWN, vi.newName)));
            }
            if (newScope.hasFreeArguments()) {
              NameContext.VarInfo<String, ?> vi;
              try {
                vi = newContext.declare("arguments", FilePosition.UNKNOWN);
              } catch (NameContext.RedeclarationException ex) {
                throw new SomethingWidgyHappenedError(
                    "Local variable unexpectedly not set", ex);
              }
              headDecls.add((Declaration) QuasiBuilder.substV(
                  "var @newName = arguments",
                  "newName", new Identifier(FilePosition.UNKNOWN, vi.newName)));
            }

            for (String local : newScope.getLocals()) {
              try {
                newContext.declare(
                    local, newScope.getLocationOfDeclaration(local));
              } catch (NameContext.RedeclarationException ex) {
                // Might occur if a var named arguments is defined.
              }
            }
            contexts.put(newScope, newContext);

            Identifier name = fc.getIdentifier();
            Identifier rewrittenName;
            if (name.getName() == null) {
              rewrittenName = name;
            } else if (!isSynthetic(name)) {
              rewrittenName = new Identifier(
                  name.getFilePosition(),
                  (isDeclaration ? context : newContext)
                  .lookup(name.getName()).newName);
            } else {
              rewrittenName = name;
            }

            List<FormalParam> newFormals = Lists.newArrayList();
            for (FormalParam p : fc.getParams()) {
              if (!isSynthetic(p.getIdentifier())) {
                NameContext.VarInfo<String, ?> v
                    = newContext.lookup(p.getIdentifierName());
                if (v == null) {
                  // Occurs when an invalid parameter appears,
                  // e.g., function (arguments) { ... }
                  try {
                    v = newContext.declare(
                        p.getIdentifierName(), p.getFilePosition());
                  } catch (NameContext.RedeclarationException ex) {
                    // If it was previously declared then v wouldn't be null.
                    throw new SomethingWidgyHappenedError(ex);
                  }
                }
                FormalParam newP = new FormalParam(new Identifier(
                    p.getFilePosition(), v.newName));
                newFormals.add(newP);
              } else {
                newFormals.add(p);
              }
            }

            // For a declaration, a name is normally introduced in both the
            // scope containing the declaration, and the function body scope.
            // We produce a declaration with the outer name, but in the inner
            // scope the function name should refer to the function itself.
            // The only exception is that if there is a local declaration
            // inside the local scope that masks the function name, then we
            // should not clobber it.
            // Examples:
            //     (function f() {
            //       var f = 0;
            //       return f;
            //     })() === 0
            // and
            //     (function f() {
            //       function f() { return 0; }
            //       return f();
            //     })() === 0
            //
            // Because the var f or inner function f masks the outer function f,
            // the name "f" should not be considered to refer to the function
            // within its body. The condition
            //     newScope.isFunction(name.getName())
            //     && !newScope.isDeclaredFunction(name.getName())
            // checks that the name still refers to the outer function, not a
            // variable or a different function that is declared within the
            // body.
            // The second clause is required because isDeclaredFunction implies
            // isDeclaredFunction but we need to distinguish the two cases.
            // For a declaration, a name is normally introduced in both the
            // scope containing the declaration, and the function body scope.
            // We produce a declaration with the outer name, but in the inner
            // scope the function name should refer to the function itself.
            // The only exception is that if there is a local declaration
            // inside the local scope that masks the function name, then we
            // should not clobber it.
            // Examples:
            //     (function f() {
            //       var f = 0;
            //       return f;
            //     })() === 0
            // and
            //     (function f() {
            //       function f() { return 0; }
            //       return f();
            //     })() === 0
            //
            // Because the var f or inner function f masks the outer function f,
            // the name "f" should not be considered to refer to the function
            // within its body. The condition
            //     newScope.isFunction(name.getName())
            //     && !newScope.isDeclaredFunction(name.getName())
            // checks that the name still refers to the outer function, not a
            // variable or a different function that is declared within the
            // body.
            // The second clause is required because isDeclaredFunction implies
            // isFunction but we need to distinguish the two cases.
            if (isDeclaration && !isSynthetic(name)
                && newScope.isFunction(name.getName())
                && !newScope.isDeclaredFunction(name.getName())) {
              headDecls.add((Declaration) QuasiBuilder.substV(
                  "var @innerName = @outerName;",
                  "outerName", new Reference(rewrittenName),
                  "innerName", new Identifier(
                      name.getFilePosition(),
                      newContext.lookup(name.getName()).newName)));
              // TODO(mikesamuel): skip if the self name is never used.
            }

            FunctionConstructor out = (FunctionConstructor) substV(
                "name", rewrittenName,
                "headDecls", optionalDeclarations(headDecls),
                "params", new ParseTreeNodeContainer(newFormals),
                "body", expandAll(bindings.get("body"), newScope));
            return isDeclaration ? new FunctionDeclaration(out) : out;
          }
          return NONE;
        }
      },

      new Rule() {
        @Override
        @RuleDescription(
            name="block",
            synopsis="block scoping",
            reason="",
            matches="{ @body* }",
            substitutes="{ @body* }")
        public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          if (node instanceof Block) {
            Block bl = (Block) node;
            List<Statement> stmts = Lists.newArrayList();
            Scope newScope = Scope.fromPlainBlock(scope);
            NameContext<String, ?> newContext = contexts.get(scope)
                .makeChildContext();
            contexts.put(newScope, newContext);
            for (String local : newScope.getLocals()) {
              try {
                newContext.declare(
                    local, newScope.getLocationOfDeclaration(local));
              } catch (NameContext.RedeclarationException ex) {
                throw new SomethingWidgyHappenedError(
                    "Local variable unexpectedly not set", ex);
              }
            }
            for (Statement s : bl.children()) {
              stmts.add((Statement) expand(s, newScope));
            }
            stmts.addAll(0, newScope.getStartStatements());
            return new Block(bl.getFilePosition(), stmts);
          }
          return NONE;
        }
      },

      new Rule() {
        @Override
        @RuleDescription(
            name="catch",
            synopsis="catch block scoping",
            reason="",
            matches="catch (@e) { @body* }",
            substitutes="catch (@e) { @body* }")
        public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          if (node instanceof CatchStmt) {
            CatchStmt cs = (CatchStmt) node;
            Scope newScope = Scope.fromCatchStmt(scope, cs);
            NameContext<String, ?> context = contexts.get(scope);
            NameContext<String, ?> newContext = context.makeChildContext();
            contexts.put(newScope, newContext);
            try {
              newContext.declare(cs.getException().getIdentifierName(),
                                 cs.getException().getFilePosition());
            } catch (NameContext.RedeclarationException ex) {
              ex.toMessageQueue(mq);
            }
            return expandAll(cs, newScope);
          }
          return NONE;
        }
      },

      //////////////
      // Renaming //
      //////////////

      new Rule() {
        @Override
        @RuleDescription(
            name="memberAccess",
            synopsis="",
            reason="so that we do not mistakenly rename property names",
            matches="@o.@r",
            substitutes="@o.@r")
        public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          Map<String, ParseTreeNode> bindings = match(node);
          if (bindings != null) {
            return substV("o", expand(bindings.get("o"), scope),
                          "r", bindings.get("r"));
          }
          return NONE;
        }
      },
      new Rule() {
        @Override
        @RuleDescription(
            name="thisReference",
            synopsis="Disallow this in the global scope.",
            reason="The declaration cannot be rewritten.",
            matches="this",
            substitutes="this")
            public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          if (match(node) != null) {
            if (scope.isOuter()) {
              mq.addMessage(
                  RewriterMessageType.THIS_IN_GLOBAL_CONTEXT,
                  node.getFilePosition());
              return new NullLiteral(node.getFilePosition());
            }
          }
          return NONE;
        }
      },
      new Rule() {
        @Override
        @RuleDescription(
            name="argumentsReference",
            synopsis="Disallow arguments in the global scope.",
            reason="The declaration cannot be rewritten.",
            matches="arguments",
            substitutes="arguments")
            public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          if (match(node) != null) {
            if (scope.isOuter()) {
              mq.addMessage(
                  RewriterMessageType.ARGUMENTS_IN_GLOBAL_CONTEXT,
                  node.getFilePosition());
              return new NullLiteral(node.getFilePosition());
            }
          }
          return NONE;
        }
      },
      new Rule() {
        @Override
        @RuleDescription(
            name="rename",
            synopsis="",
            reason="",
            matches="/* Reference */ @r",
            substitutes="@r")
        public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          if (node instanceof Reference) {
            Reference r = (Reference) node;
            if (!isSynthetic(r)) {
              FilePosition pos = r.getFilePosition();
              String rname = r.getIdentifierName();
              NameContext<String, ?> context = contexts.get(scope);
              NameContext.VarInfo<String, ?> vi = context.lookup(rname);
              if (vi != null) {
                return new Reference(new Identifier(pos, vi.newName));
              } else {
                mq.addMessage(
                    RewriterMessageType.FREE_VARIABLE, pos,
                    MessagePart.Factory.valueOf(rname));
                return new NullLiteral(pos);
              }
            }
          }
          return NONE;
        }
      },
      new Rule() {
        @Override
        @RuleDescription(
            name="decl",
            synopsis="rewrite declaration identifiers",
            reason="",
            matches="var @i = @v?",
            substitutes="var @ri = @v?;")
        public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
          Map<String, ParseTreeNode> bindings = match(node);
          if (bindings != null) {
            Identifier i = (Identifier) bindings.get("i");
            Expression v = (Expression) bindings.get("v");
            Identifier ri;
            if (!isSynthetic(i)) {
              NameContext<String, ?> context = contexts.get(scope);
              NameContext.VarInfo<String, ?> var = context.lookup(i.getName());
              if (var == null) {  // A variable like arguments
                return expandAll(node, scope);
              }
              ri = new Identifier(i.getFilePosition(), var.newName);
            } else {
              ri = i;
            }
            return substV(
                "ri", ri,
View Full Code Here

  /**
   * Add an error to the queue if an identifier contains non-ASCII characters.
   */
  public boolean visit(ParseTreeNode node) {
    if (!(node instanceof Identifier)) { return true; }
    Identifier ident = (Identifier) node;
    String name = ident.getName();
    if (!SyntheticNodes.is(ident)
        && name != null && !name.matches("^[a-zA-Z_$][a-zA-Z0-9_$]*$")) {
      mq.addMessage(
          RewriterMessageType.NONASCII_IDENTIFIER,
          node.getFilePosition(), node);
View Full Code Here

    // the correct nodes marked synthetic.
    boolean isSynthetic = false;
    if (hasSyntheticAnnotation(n)) {
      isSynthetic = true;
    } else if (n instanceof Identifier) {
      Identifier ident = (Identifier) n;
      isSynthetic = ident.getName() != null && ident.getName().endsWith("__");
    } else if (n instanceof Reference) {
      Reference ref = (Reference) n;
      isSynthetic = ref.getIdentifierName().endsWith("__");
    }
View Full Code Here

            continue;
          }
        }
        QuasiNode keyQuasi = build(
            keyIdent != null
            ? new Reference(new Identifier(FilePosition.UNKNOWN, keyIdent))
            : key);
        propQuasis.add(new SinglePropertyQuasi(keyQuasi, build(value)));
      } else {
        // TODO: support getters and setters in object quasis
        throw new UnsupportedOperationException(prop.getClass().getName());
View Full Code Here

    }
    return n;
  }

  public static Reference newReference(FilePosition pos, String name) {
    return new Reference(s(new Identifier(pos, name)));
  }
View Full Code Here

  protected ParseTreeNode nymize(ParseTreeNode node, String baseName, String ext) {
    Map<String, ParseTreeNode> bindings = makeBindings();
    if (QuasiBuilder.match("function (@ps*) {@bs*;}", node, bindings)) {
      return QuasiBuilder.substV(
          "function @fname(@ps*) {@bs*;}",
          "fname", new Identifier(
              FilePosition.startOf(node.getFilePosition()),
              nym(node, baseName, ext)),
          "ps", bindings.get("ps"),
          "bs", bindings.get("bs"));
    }
View Full Code Here

TOP

Related Classes of com.google.caja.parser.js.Identifier

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.