use of com.google.javascript.rhino.FunctionTypeI in project closure-compiler by google.
the class CheckNullableReturn method isReturnTypeNullable.
/**
* @return True if n is a function node which is explicitly annotated
* as returning a nullable type, other than {?}.
*/
private static boolean isReturnTypeNullable(Node n) {
if (n == null || !n.isFunction()) {
return false;
}
FunctionTypeI functionType = n.getTypeI().toMaybeFunctionType();
if (functionType == null) {
// If the JSDoc declares a non-function type on a function node, we still shouldn't crash.
return false;
}
TypeI returnType = functionType.getReturnType();
if (returnType == null || returnType.isUnknownType() || !returnType.isNullable()) {
return false;
}
JSDocInfo info = NodeUtil.getBestJSDocInfo(n);
return info != null && info.hasReturnType();
}
use of com.google.javascript.rhino.FunctionTypeI in project closure-compiler by google.
the class TypedCodeGenerator method getFunctionAnnotation.
/**
* @param fnNode A node for a function for which to generate a type annotation
*/
private String getFunctionAnnotation(Node fnNode) {
TypeI type = fnNode.getTypeI();
checkState(fnNode.isFunction() || type.isFunctionType());
if (type == null || type.isUnknownType()) {
return "";
}
FunctionTypeI funType = type.toMaybeFunctionType();
if (type.equals(registry.getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE))) {
return "/** @type {!Function} */\n";
}
StringBuilder sb = new StringBuilder("/**\n");
Node paramNode = null;
// NAME param2
if (fnNode != null && fnNode.isFunction()) {
paramNode = NodeUtil.getFunctionParameters(fnNode).getFirstChild();
}
// Param types
int minArity = funType.getMinArity();
int maxArity = funType.getMaxArity();
List<TypeI> formals = ImmutableList.copyOf(funType.getParameterTypes());
for (int i = 0; i < formals.size(); i++) {
sb.append(" * ");
appendAnnotation(sb, "param", getParameterJSDocType(formals, i, minArity, maxArity));
sb.append(" ").append(paramNode == null ? "p" + i : paramNode.getString()).append("\n");
if (paramNode != null) {
paramNode = paramNode.getNext();
}
}
// Return type
TypeI retType = funType.getReturnType();
if (retType != null && // There is no annotation for the empty type.
!retType.isBottom() && // Interfaces never return a value.
!funType.isInterface() && !(funType.isConstructor() && retType.isVoidType())) {
sb.append(" * ");
appendAnnotation(sb, "return", retType.toAnnotationString(Nullability.EXPLICIT));
sb.append("\n");
}
if (funType.isConstructor()) {
appendConstructorAnnotations(sb, funType);
} else if (funType.isInterface()) {
appendInterfaceAnnotations(sb, funType);
} else {
TypeI thisType = funType.getTypeOfThis();
if (thisType != null && !thisType.isUnknownType() && !thisType.isVoidType()) {
if (fnNode == null || !thisType.equals(findMethodOwner(fnNode))) {
sb.append(" * ");
appendAnnotation(sb, "this", thisType.toAnnotationString(Nullability.EXPLICIT));
sb.append("\n");
}
}
}
Collection<TypeI> typeParams = funType.getTypeParameters();
if (!typeParams.isEmpty()) {
sb.append(" * @template ");
Joiner.on(",").appendTo(sb, Iterables.transform(typeParams, new Function<TypeI, String>() {
@Override
public String apply(TypeI var) {
return formatTypeVar(var);
}
}));
sb.append("\n");
}
sb.append(" */\n");
return sb.toString();
}
use of com.google.javascript.rhino.FunctionTypeI in project closure-compiler by google.
the class TypedCodeGenerator method appendConstructorAnnotations.
// TODO(dimvar): it's awkward that we print @constructor after the extends/implements;
// we should print it first, like users write it. Same for @interface and @record.
private void appendConstructorAnnotations(StringBuilder sb, FunctionTypeI funType) {
FunctionTypeI superConstructor = funType.getInstanceType().getSuperClassConstructor();
if (superConstructor != null) {
ObjectTypeI superInstance = superConstructor.getInstanceType();
if (!superInstance.toString().equals("Object")) {
sb.append(" * ");
appendAnnotation(sb, "extends", superInstance.toAnnotationString(Nullability.IMPLICIT));
sb.append("\n");
}
}
// Avoid duplicates, add implemented type to a set first
Set<String> interfaces = new TreeSet<>();
for (ObjectTypeI interfaze : funType.getAncestorInterfaces()) {
interfaces.add(interfaze.toAnnotationString(Nullability.IMPLICIT));
}
for (String interfaze : interfaces) {
sb.append(" * ");
appendAnnotation(sb, "implements", interfaze);
sb.append("\n");
}
sb.append(" * @constructor\n");
}
use of com.google.javascript.rhino.FunctionTypeI in project closure-compiler by google.
the class AmbiguateProperties method computeRelatedTypes.
/**
* Adds subtypes - and implementors, in the case of interfaces - of the type
* to its JSTypeBitSet of related types. Union types are decomposed into their
* alternative types.
*
* <p>The 'is related to' relationship is best understood graphically. Draw an
* arrow from each instance type to the prototype of each of its
* subclass. Draw an arrow from each prototype to its instance type. Draw an
* arrow from each interface to its implementors. A type is related to another
* if there is a directed path in the graph from the type to other. Thus, the
* 'is related to' relationship is reflexive and transitive.
*
* <p>Example with Foo extends Bar which extends Baz and Bar implements I:
* <pre>{@code
* Foo -> Bar.prototype -> Bar -> Baz.prototype -> Baz
* ^
* |
* I
* }</pre>
*
* <p>Note that we don't need to correctly handle the relationships between
* functions, because the function type is invalidating (i.e. its properties
* won't be ambiguated).
*/
private void computeRelatedTypes(TypeI type) {
if (type.isUnionType()) {
type = type.restrictByNotNullOrUndefined();
if (type.isUnionType()) {
for (TypeI alt : type.getUnionMembers()) {
computeRelatedTypes(alt);
}
return;
}
}
if (relatedBitsets.containsKey(type)) {
// We only need to generate the bit set once.
return;
}
JSTypeBitSet related = new JSTypeBitSet(intForType.size());
relatedBitsets.put(type, related);
related.set(getIntForType(type));
// A prototype is related to its instance.
if (type.isPrototypeObject()) {
FunctionTypeI maybeCtor = type.toMaybeObjectType().getOwnerFunction();
if (maybeCtor.isConstructor() || maybeCtor.isInterface()) {
addRelatedInstance(maybeCtor, related);
}
return;
}
// A class/interface is related to its subclasses/implementors.
FunctionTypeI constructor = type.toMaybeObjectType().getConstructor();
if (constructor != null) {
for (FunctionTypeI subType : constructor.getDirectSubTypes()) {
addRelatedInstance(subType, related);
}
}
}
use of com.google.javascript.rhino.FunctionTypeI in project closure-compiler by google.
the class AstValidator method validateCallType.
private void validateCallType(Node callNode) {
// TODO(b/74537281): Shouldn't CALL nodes always have a type, even if it is unknown?
Node callee = callNode.getFirstChild();
TypeI calleeTypeI = checkNotNull(callee.getTypeI(), callNode);
if (calleeTypeI.isFunctionType()) {
FunctionTypeI calleeFunctionTypeI = calleeTypeI.toMaybeFunctionType();
TypeI returnTypeI = calleeFunctionTypeI.getReturnType();
// TODO(b/74537281): This will fail after CAST nodes have been removed from the AST.
// Must be fixed before this check can be done after optimizations.
expectMatchingTypeInformation(callNode, returnTypeI);
}
// TODO(b/74537281): What other cases should be covered?
}
Aggregations