/** Returns the node's pre-CAST type, if is has one. Otherwise just returns node.getJSType() */ private static JSType getTypeBeforeCast(Node node) { JSType typeBeforeCast = node.getJSTypeBeforeCast(); // might still return null if node.getJSType() is null (i.e. typechecking hasn't run) return typeBeforeCast != null ? typeBeforeCast : node.getJSType(); }
/** * This method gets the JSType from the Node argument and verifies that it is * present. */ private JSType getJSType(Node n) { return checkNotNull(n.getJSType(), "%s has no JSType attached", n); }
private boolean isConstructor(Node n) { // If type checking is enabled (not just a per-file lint check), // we can check constructor properties too. But it isn't required. JSType type = n.getJSType(); return type != null && (type.isConstructor() || type.isInterface()); } }
private void expectMatchingTypeInformation(Node n, JSType expectedTypeI) { JSType typeI = n.getJSType(); if (!Objects.equals(expectedTypeI, typeI)) { violation( "Expected type: " + getTypeAnnotationString(expectedTypeI) + " Actual type: " + getTypeAnnotationString(typeI), n); } }
Node createComputedProperty(Node key, Node value) { Node result = IR.computedProp(key, value); if (isAddingTypes()) { result.setJSType(value.getJSType()); } return result; }
Node createComma(Node left, Node right) { Node result = IR.comma(left, right); if (isAddingTypes()) { result.setJSType(right.getJSType()); } return result; }
private Node callInferringJSType(Node callee, Node... args) { Node call = IR.call(callee, args); JSType calleeType = callee.getJSType(); if (calleeType == null || !(calleeType instanceof FunctionType)) { return call; } JSType returnType = ((FunctionType) calleeType).getReturnType(); return call.setJSType(returnType); } }
private boolean invalidDeref(Node n) { JSType type = n.getJSType(); // TODO(johnlenz): top type should not be allowed here return !type.isAllType() && (type.isNullable() || type.isVoidable()); } }
boolean report(Node n) { return n.getJSType() != null && isKnown(n) && invalidDeref(n) && !isWhitelistedType(n); }
private JSType convertMethodToFunction(FunctionType method) { List<JSType> paramTypes = new ArrayList<>(); paramTypes.add(method.getTypeOfThis()); for (Node param : method.getParameters()) { paramTypes.add(param.getJSType()); } ObjectType unknown = compiler.getTypeRegistry().getNativeObjectType(JSTypeNative.UNKNOWN_TYPE); return compiler.getTypeRegistry().createFunctionTypeWithInstanceType( unknown, method.getReturnType(), paramTypes); }
boolean hasUnknownParamsOrReturn() { if (parameters != null) { for (Node paramNode = parameters.getFirstChild(); paramNode != null; paramNode = paramNode.getNext()) { JSType type = paramNode.getJSType(); if (type == null || type.isUnknownType()) { return true; } } } return returnType == null || returnType.isUnknownType(); }
/** * @return True if the node represents a nullable value. Essentially, this * is just n.getJSType().isNullable(), but for purposes of this pass, * the expression {@code x || null} is considered nullable even if * x is always truthy. This often happens with expressions like * {@code arr[i] || null}: The compiler doesn't know that arr[i] can * be undefined. */ private static boolean isNullable(Node n) { return n.getJSType().isNullable() || (n.isOr() && n.getLastChild().isNull()); }
private Node getpropInferringJSType(Node receiver, String propName) { Node getprop = IR.getprop(receiver, propName); JSType receiverType = receiver.getJSType(); if (receiverType == null) { return getprop; } JSType getpropType = receiverType.findPropertyType(propName); if (getpropType == null && receiverType instanceof FunctionType) { getpropType = ((FunctionType) receiverType).getPropertyType(propName); } return getprop.setJSType(getpropType); }
/** * @return True if the node represents a nullable value. Essentially, this * is just n.getJSType().isNullable(), but for purposes of this pass, * the expression {@code x || null} is considered nullable even if * x is always truthy. This often happens with expressions like * {@code arr[i] || null}: The compiler doesn't know that arr[i] can * be undefined. */ private static boolean isNullable(Node n) { return n.getJSType().isNullable() || (n.isOr() && n.getLastChild().isNull()); }
/** * Copies the parameter specification from the given node. */ public Node newParameterFromNode(Node n) { Node newParam = newParameter(n.getJSType()); newParam.setVarArgs(n.isVarArgs()); newParam.setOptionalArg(n.isOptionalArg()); return newParam; }
@Override JSType resolveInternal(ErrorReporter reporter) { returnType = safeResolve(returnType, reporter); if (parameters != null) { for (Node paramNode = parameters.getFirstChild(); paramNode != null; paramNode = paramNode.getNext()) { paramNode.setJSType(paramNode.getJSType().resolve(reporter)); } } return this; }
@Override public boolean isStaticProperty() { Node lhs = assignNode.getFirstChild(); if (lhs.isGetProp()) { // something.propName = someValue Node getPropLhs = lhs.getFirstChild(); JSType typeI = getPropLhs.getJSType(); return typeI != null && (typeI.isConstructor() || typeI.isInterface()); } else { return false; } }
static boolean isConstructor(Node fnNode) { if (fnNode == null || !fnNode.isFunction()) { return false; } JSType type = fnNode.getJSType(); JSDocInfo jsDocInfo = getBestJSDocInfo(fnNode); return (type != null && type.isConstructor()) || (jsDocInfo != null && jsDocInfo.isConstructor()) || isEs6Constructor(fnNode); }
@Override public void visit(NodeTraversal t, Node n, Node parent) { if (n.isThis()) { Node superThis = astFactory.createName(SUPER_THIS, n.getJSType()).useSourceInfoFrom(n); parent.replaceChild(n, superThis); } else if (n.isReturn() && !n.hasChildren()) { // An empty return needs to be changed to return $jscomp$super$this n.addChildToFront(astFactory.createName(SUPER_THIS, typeOfThis).useSourceInfoFrom(n)); } } };