@Override public Node getRootNode() { return delegate.getRootNode(); }
@Override public StaticTypedSlot getSlot(String name) { return delegate.getSlot(name); }
@Override public JSType getTypeOfThis() { return delegate.getTypeOfThis(); } }
@CheckReturnValue private FlowScope inferDeclarativelyUnboundVarsWithoutTypes(FlowScope flow) { TypedScope scope = (TypedScope) flow.getDeclarationScope(); if (!inferredUnboundVars.add(scope)) { return flow; } // For each local variable declared with the VAR keyword, the entry // type is VOID. for (TypedVar var : scope.getDeclarativelyUnboundVarsWithoutTypes()) { if (isUnflowable(var)) { continue; } flow = flow.inferSlotType(var.getName(), getNativeType(VOID_TYPE)); } return flow; }
private FlowScope caseAndOrMaybeShortCircuiting(Node left, Node right, FlowScope blindScope, boolean outcome) { FlowScope leftScope = firstPreciserScopeKnowingConditionOutcome( left, blindScope, !outcome); StaticTypedSlot<JSType> leftVar = leftScope.findUniqueRefinedSlot(blindScope); if (leftVar == null) { // If we did create a more precise scope, blindScope has a child and // it is frozen. We can't just throw it away to return it. So we // must create a child instead. return blindScope == leftScope ? blindScope : blindScope.createChildFlowScope(); } FlowScope rightScope = firstPreciserScopeKnowingConditionOutcome( left, blindScope, outcome); rightScope = firstPreciserScopeKnowingConditionOutcome( right, rightScope, !outcome); StaticTypedSlot<JSType> rightVar = rightScope.findUniqueRefinedSlot(blindScope); if (rightVar == null || !leftVar.getName().equals(rightVar.getName())) { return blindScope == rightScope ? blindScope : blindScope.createChildFlowScope(); } JSType type = leftVar.getType().getLeastSupertype(rightVar.getType()); FlowScope informed = blindScope.createChildFlowScope(); informed.inferSlotType(leftVar.getName(), type); return informed; }
private FlowScope narrowScope(FlowScope scope, Node node, JSType narrowed) { if (node.isThis()) { // "this" references don't need to be modeled in the control flow graph. return scope; } scope = scope.createChildFlowScope(); if (node.isGetProp()) { scope.inferQualifiedSlot( node, node.getQualifiedName(), getJSType(node), narrowed, false); } else { redeclareSimpleVar(scope, node, narrowed); } return scope; }
/** * Declares a refined type in {@code scope} for the name represented by {@code node}. It must be * possible to refine the type of the given node in the given scope, as determined by {@link * #getTypeIfRefinable}. Returns an updated flow scope, which may be different from the passed-in * scope if any changes occur. */ @CheckReturnValue protected FlowScope declareNameInScope(FlowScope scope, Node node, JSType type) { switch (node.getToken()) { case NAME: return scope.inferSlotType(node.getString(), type); case GETPROP: String qualifiedName = node.getQualifiedName(); checkNotNull(qualifiedName); JSType origType = node.getJSType(); origType = origType == null ? getNativeType(UNKNOWN_TYPE) : origType; return scope.inferQualifiedSlot(node, qualifiedName, origType, type, false); case THIS: // "this" references aren't currently modeled in the CFG. return scope; default: throw new IllegalArgumentException("Node cannot be refined. \n" + node.toStringTree()); } }
if (qualifiedName != null) { String propertyQualifiedName = qualifiedName + "." + propertyName; if (blindScope.getSlot(propertyQualifiedName) == null) { FlowScope informed = blindScope.createChildFlowScope(); JSType unknownType = typeRegistry.getNativeType( JSTypeNative.UNKNOWN_TYPE); informed.inferQualifiedSlot( object, propertyQualifiedName, unknownType, unknownType, false); return informed;
@Override public FlowScope inferQualifiedSlot( Node node, String symbol, JSType bottomType, JSType inferredType, boolean declare) { refinements.add(symbol); return wrap(delegate.inferQualifiedSlot(node, symbol, bottomType, inferredType, declare)); }
FlowScope leftScope = firstPreciserScopeKnowingConditionOutcome(left, blindScope, !outcome); StaticTypedSlot leftVar = refinements.size() == 1 ? leftScope.getSlot(refinements.iterator().next()) : null; if (leftVar == null) { rightScope = firstPreciserScopeKnowingConditionOutcome(right, rightScope, !outcome); StaticTypedSlot rightVar = refinements.size() == 1 ? rightScope.getSlot(refinements.iterator().next()) : null; if (rightVar == null || !leftVar.getName().equals(rightVar.getName())) { return unwrap(blindScope); return unwrap(blindScope).inferSlotType(leftVar.getName(), type);
if (qualifiedName != null) { String propertyQualifiedName = qualifiedName + "." + propertyName; if (blindScope.getSlot(propertyQualifiedName) == null) { JSType unknownType = typeRegistry.getNativeType(JSTypeNative.UNKNOWN_TYPE); return blindScope.inferQualifiedSlot( object, propertyQualifiedName, unknownType, unknownType, false);
@Override public FlowScope inferSlotType(String symbol, JSType type) { refinements.add(symbol); return wrap(delegate.inferSlotType(symbol, type)); }
StaticTypedSlot var = qualifiedName != null ? scope.getSlot(qualifiedName) : null; if (var != null) { JSType varType = var.getType(); registry.getType(scope.getDeclarationScope(), qualifiedName)); if (regType != null) { propertyType = regType.getConstructor();
.createChildFlowScope(); break; .createChildFlowScope(); break; n.setJSType(scope.getTypeOfThis()); break;
n.setJSType(scope.getTypeOfThis()); break; JSDocInfo info = n.getJSDocInfo(); if (info != null && info.hasType()) { n.setJSType(info.getType().evaluate(scope.getDeclarationScope(), registry));
@Override FlowScope flowThrough(Node n, FlowScope input) { // If we have not walked a path from <entry> to <n>, then we don't // want to infer anything about this scope. if (input == bottomScope) { return input; } FlowScope output = input.createChildFlowScope(); output = traverse(n, output); return output; }
Node obj = item.getNext(); FlowScope informed = traverse(obj, output.createChildFlowScope()); condition.getFirstChild(), output.createChildFlowScope()); traverseAnd(condition, output.createChildFlowScope()) : traverseOr(condition, output.createChildFlowScope()); traverse(condition, output.createChildFlowScope()); result.add(newScope.optimize());
@Override public StaticTypedScope getDeclarationScope() { return delegate.getDeclarationScope(); }
@Override public StaticTypedSlot getOwnSlot(String name) { return delegate.getOwnSlot(name); }
/** * Declares a refined type in {@code scope} for the name represented by * {@code node}. It must be possible to refine the type of the given node in * the given scope, as determined by {@link #getTypeIfRefinable}. */ protected void declareNameInScope(FlowScope scope, Node node, JSType type) { switch (node.getType()) { case Token.NAME: scope.inferSlotType(node.getString(), type); break; case Token.GETPROP: String qualifiedName = node.getQualifiedName(); Preconditions.checkNotNull(qualifiedName); JSType origType = node.getJSType(); origType = origType == null ? getNativeType(UNKNOWN_TYPE) : origType; scope.inferQualifiedSlot(node, qualifiedName, origType, type, false); break; case Token.THIS: // "this" references aren't currently modeled in the CFG. break; default: throw new IllegalArgumentException("Node cannot be refined. \n" + node.toStringTree()); } }