use of com.google.javascript.jscomp.GlobalNamespace.Ref in project closure-compiler by google.
the class GlobalNamespaceTest method confirmTwinsAreCreated.
@Test
public void confirmTwinsAreCreated() {
GlobalNamespace namespace = parse(lines(//
"let A;", // A will have twin refs here
"const B = A = 3;"));
Name nameA = namespace.getOwnSlot("A");
// first ref is declaration of A
// second is the SET twin
Ref setTwinRef = Iterables.get(nameA.getRefs(), 1);
// third is the GET twin
Ref getTwinRef = Iterables.get(nameA.getRefs(), 2);
// confirm that they start as twins
assertThat(setTwinRef.getTwin()).isEqualTo(getTwinRef);
assertThat(getTwinRef.getTwin()).isEqualTo(setTwinRef);
Node oldNode = getTwinRef.getNode();
assertThat(setTwinRef.getNode()).isEqualTo(oldNode);
// confirm that they are both associated with oldNode
assertThat(nameA.getRefsForNode(oldNode)).containsExactly(setTwinRef, getTwinRef);
}
use of com.google.javascript.jscomp.GlobalNamespace.Ref in project closure-compiler by google.
the class GlobalNamespaceTest method updateRefNodeMovesRefFromOldNodeToNewNode.
@Test
public void updateRefNodeMovesRefFromOldNodeToNewNode() {
GlobalNamespace namespace = parse("const A = 3;");
Name nameA = namespace.getOwnSlot("A");
Ref refA = nameA.getFirstRef();
Node oldNode = refA.getNode();
Node newNode = IR.name("A");
assertThat(nameA.getRefsForNode(oldNode)).containsExactly(refA);
nameA.updateRefNode(refA, newNode);
assertThat(refA.getNode()).isEqualTo(newNode);
assertThat(nameA.getRefsForNode(oldNode)).isEmpty();
assertThat(nameA.getRefsForNode(newNode)).containsExactly(refA);
}
use of com.google.javascript.jscomp.GlobalNamespace.Ref in project closure-compiler by google.
the class GlobalNamespaceTest method updateRefNodeCanSetNodeToNullButPreventsFurtherUpdates.
@Test
public void updateRefNodeCanSetNodeToNullButPreventsFurtherUpdates() {
GlobalNamespace namespace = parse("const A = 3;");
Name nameA = namespace.getOwnSlot("A");
Ref refA = nameA.getFirstRef();
Node oldNode = refA.getNode();
assertThat(nameA.getRefsForNode(oldNode)).containsExactly(refA);
nameA.updateRefNode(refA, null);
assertThat(refA.getNode()).isNull();
assertThat(nameA.getRefsForNode(oldNode)).isEmpty();
// cannot get refs for null
assertThrows(NullPointerException.class, () -> nameA.getRefsForNode(null));
// cannot update the node again once it's been set to null
assertThrows(IllegalArgumentException.class, () -> nameA.updateRefNode(refA, null));
assertThrows(IllegalStateException.class, () -> nameA.updateRefNode(refA, oldNode));
}
use of com.google.javascript.jscomp.GlobalNamespace.Ref in project closure-compiler by google.
the class GlobalNamespaceTest method updateRefNodeRejectsNodeWithExistingRefs.
@Test
public void updateRefNodeRejectsNodeWithExistingRefs() {
GlobalNamespace namespace = parse(lines(// declaration ref
"const A = 3;", // use ref
"A;"));
Name nameA = namespace.getOwnSlot("A");
Ref declarationRef = nameA.getDeclaration();
// use ref is 2nd
Ref useRef = Iterables.get(nameA.getRefs(), 1);
Node useNode = useRef.getNode();
assertThrows(IllegalArgumentException.class, () -> nameA.updateRefNode(declarationRef, useNode));
}
use of com.google.javascript.jscomp.GlobalNamespace.Ref in project closure-compiler by google.
the class PolymerBehaviorExtractor method extractBehaviors.
/**
* Extracts all Behaviors from an array literal, recursively. Entries in the array can be
* object literals or array literals (of other behaviors). Behavior names must be
* global, fully qualified names.
* @see https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md#behaviors
* @return A list of all {@code BehaviorDefinitions} in the array.
*/
ImmutableList<BehaviorDefinition> extractBehaviors(Node behaviorArray) {
if (behaviorArray == null) {
return ImmutableList.of();
}
if (!behaviorArray.isArrayLit()) {
compiler.report(JSError.make(behaviorArray, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR_ARRAY));
return ImmutableList.of();
}
ImmutableList.Builder<BehaviorDefinition> behaviors = ImmutableList.builder();
for (Node behaviorName : behaviorArray.children()) {
if (behaviorName.isObjectLit()) {
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorName, compiler);
PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorName, compiler);
if (NodeUtil.getFirstPropMatchingKey(behaviorName, "is") != null) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
}
behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorName, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler), getBehaviorFunctionsToCopy(behaviorName), getNonPropertyMembersToCopy(behaviorName), !NodeUtil.isInFunction(behaviorName), (FeatureSet) NodeUtil.getEnclosingScript(behaviorName).getProp(Node.FEATURE_SET)));
continue;
}
Name behaviorGlobalName = globalNames.getSlot(behaviorName.getQualifiedName());
boolean isGlobalDeclaration = true;
if (behaviorGlobalName == null) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
continue;
}
Ref behaviorDeclaration = behaviorGlobalName.getDeclaration();
// Use any set as a backup declaration, even if it's local.
if (behaviorDeclaration == null) {
List<Ref> behaviorRefs = behaviorGlobalName.getRefs();
for (Ref ref : behaviorRefs) {
if (ref.isSet()) {
isGlobalDeclaration = false;
behaviorDeclaration = ref;
break;
}
}
}
if (behaviorDeclaration == null) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
continue;
}
Node behaviorDeclarationNode = behaviorDeclaration.getNode();
JSDocInfo behaviorInfo = NodeUtil.getBestJSDocInfo(behaviorDeclarationNode);
if (behaviorInfo == null || !behaviorInfo.isPolymerBehavior()) {
compiler.report(JSError.make(behaviorDeclarationNode, PolymerPassErrors.POLYMER_UNANNOTATED_BEHAVIOR));
}
Node behaviorValue = NodeUtil.getRValueOfLValue(behaviorDeclarationNode);
if (behaviorValue == null) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
} else if (behaviorValue.isArrayLit()) {
// Individual behaviors can also be arrays of behaviors. Parse them recursively.
behaviors.addAll(extractBehaviors(behaviorValue));
} else if (behaviorValue.isObjectLit()) {
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorValue, compiler);
PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorValue, compiler);
if (NodeUtil.getFirstPropMatchingKey(behaviorValue, "is") != null) {
compiler.report(JSError.make(behaviorValue, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
}
behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorValue, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler), getBehaviorFunctionsToCopy(behaviorValue), getNonPropertyMembersToCopy(behaviorValue), isGlobalDeclaration, (FeatureSet) NodeUtil.getEnclosingScript(behaviorValue).getProp(Node.FEATURE_SET)));
} else {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
}
}
return behaviors.build();
}
Aggregations