// Copyright (C) 2006 Google Inc.
//
// Licensed 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 com.google.caja.parser.js;
import com.google.caja.parser.AbstractParseTreeNode;
import com.google.caja.parser.ParseTreeNode;
/**
* Defines a Synthetic Attribute that marks a node as having been generated
* as part of the compilation process.
* <p>
* Such nodes can be exempted from scrutiny by other nodes. For example,
* javascript identifiers in the {@code *__} namespace are reserved for
* use by Caja runtime checks.
* {@link com.google.caja.parser.js.Reference}s and
* {@link com.google.caja.parser.js.Declaration}s
* generated by the Caja compile with names like that should be marked synthetic
* so that they won't be rejected by the validator. But since user code is
* not synthetic, they will be rejected by the validator.
*
* @author mikesamuel@gmail.com
*/
public final class SyntheticNodes {
public static boolean isSynthesizable(ParseTreeNode node) {
return (node instanceof Identifier && node.getValue() != null)
|| node instanceof FunctionConstructor
|| node instanceof UncajoledModule;
}
public static boolean is(ParseTreeNode t) {
return t instanceof AbstractParseTreeNode
&& ((AbstractParseTreeNode) t).isSynthetic();
}
/**
* A convenience function used to mark {@link #isSynthesizable synthesizable}
* nodes created during source->javascript translation as
* {@link AbstractParseTreeNode#isSynthetic synthetic}.
* Nodes corresponding to javascript embedded in the original will not be
* synthetic.
* <p>
* This is meant to be imported statically.
*/
public static <T extends ParseTreeNode> T s(T t) {
if (isSynthesizable(t)) {
((AbstractParseTreeNode) t).setSynthetic(true);
}
return t;
}
/** A synthetic identifier may occupy the <code>*__</code> namespace. */
public static Identifier s(Identifier t) {
t.setSynthetic(true);
return t;
}
/**
* Temporaries created as a result of rewriting operations inside a synthetic
* function are actually declared in the closest non-synthetic enclosing
* function.
*/
public static FunctionConstructor s(FunctionConstructor t) {
t.setSynthetic(true);
return t;
}
public static Block s(Block t) {
t.setSynthetic(true);
return t;
}
private SyntheticNodes() { /* uninstantiable */ }
}