private void warnInvalid(String msg, Node e) { addNewWarning("msg.jsdoc.typetransformation.invalid", msg, e); }
/** * A typeOfVar expression must be of the form instanceOf('name') */ private boolean validInstanceOfExpression(Node expr) { // The expression must have two children: // - The instanceOf keyword // - A string if (!checkParameterCount(expr, Keywords.INSTANCEOF)) { return false; } if (!validTypeTransformationExpression(getCallArgument(expr, 0))) { warnInvalidInside(Keywords.INSTANCEOF.name, expr); return false; } return true; }
/** * A record type expression must be of the form: * record(RecordExp, RecordExp, ...) */ private boolean validRecordTypeExpression(Node expr) { // The expression must have at least two children. The record keyword and // a record expression if (!checkParameterCount(expr, Keywords.RECORD)) { return false; } // Each child must be a valid record for (int i = 0; i < getCallParamCount(expr); i++) { if (!validRecordParam(getCallArgument(expr, i))) { warnInvalidInside(Keywords.RECORD.name, expr); return false; } } return true; }
private boolean checkParameterCount(Node expr, Keywords keyword) { int paramCount = getCallParamCount(expr); if (paramCount < keyword.minParamCount) { warnMissingParam(keyword.name, expr); return false; } if (paramCount > keyword.maxParamCount) { warnExtraParam(keyword.name, expr); return false; } return true; }
private boolean validStringPredicate(Node expr, int paramCount) { // Each parameter must be valid string parameter for (int i = 0; i < paramCount; i++) { if (!isValidStringParam(getCallArgument(expr, i))) { warnInvalidInside("boolean", expr); return false; } } return true; }
private boolean validTypePredicate(Node expr, int paramCount) { // All the types must be valid type expressions for (int i = 0; i < paramCount; i++) { if (!validTypeTransformationExpression(getCallArgument(expr, i))) { warnInvalidInside("boolean", expr); return false; } } return true; }
if (isBooleanOperation(expr)) { return validBooleanOperation(expr); if (!isOperation(expr)) { warnInvalidExpression("boolean", expr); return false; if (!isValidPredicate(getCallName(expr))) { warnInvalid("boolean predicate", expr); return false; Keywords keyword = nameToKeyword(getCallName(expr)); if (!checkParameterCount(expr, keyword)) { return false; return validTypePredicate(expr, getCallParamCount(expr)); case STRING_PREDICATE: return validStringPredicate(expr, getCallParamCount(expr)); case TYPEVAR_PREDICATE: return validTypevarPredicate(expr, getCallParamCount(expr)); default: throw new IllegalStateException("Invalid boolean expression");
if (!checkParameterCount(expr, Keywords.MAPUNION)) { return false; if (!validTypeTransformationExpression(getCallArgument(expr, 0))) { warnInvalidInside(Keywords.MAPUNION.name, getCallArgument(expr, 0)); return false; if (!getCallArgument(expr, 1).isFunction()) { warnInvalid("map function", getCallArgument(expr, 1)); warnInvalidInside(Keywords.MAPUNION.name, getCallArgument(expr, 1)); return false; Node mapFn = getCallArgument(expr, 1); int mapFnParamCount = getFunctionParamCount(mapFn); if (mapFnParamCount < 1) { warnMissingParam("map function", mapFn); warnInvalidInside(Keywords.MAPUNION.name, getCallArgument(expr, 1)); return false; warnExtraParam("map function", mapFn); warnInvalidInside(Keywords.MAPUNION.name, getCallArgument(expr, 1)); return false; Node mapFnBody = getFunctionBody(mapFn); if (!validTypeTransformationExpression(mapFnBody)) { warnInvalidInside("map function body", mapFnBody); return false;
/** * A TTL type expression must be a union type, a template type, a record type * or any of the type predicates (none, rawTypeOf, templateTypeOf). */ private boolean validTypeExpression(Node expr) { String name = getCallName(expr); Keywords keyword = nameToKeyword(name); switch (keyword) { case TYPE: return validTemplateTypeExpression(expr); case UNION: return validUnionTypeExpression(expr); case NONE: return validNoneTypeExpression(expr); case ALL: return validAllTypeExpression(expr); case UNKNOWN: return validUnknownTypeExpression(expr); case RAWTYPEOF: return validRawTypeOfTypeExpression(expr); case TEMPLATETYPEOF: return validTemplateTypeOfExpression(expr); case RECORD: return validRecordTypeExpression(expr); case TYPEEXPR: return validNativeTypeExpr(expr); default: throw new IllegalStateException("Invalid type expression"); } }
/** * An operation expression is a cond or a mapunion */ private boolean validOperationExpression(Node expr) { String name = getCallName(expr); Keywords keyword = nameToKeyword(name); switch (keyword) { case COND: return validConditionalExpression(expr); case MAPUNION: return validMapunionExpression(expr); case MAPRECORD: return validMaprecordExpression(expr); case TYPEOFVAR: return validTypeOfVarExpression(expr); case INSTANCEOF: return validInstanceOfExpression(expr); case PRINTTYPE: return validPrintTypeExpression(expr); case PROPTYPE: return validPropTypeExpression(expr); default: throw new IllegalStateException("Invalid type transformation operation"); } }
/** * Checks the structure of the AST of a type transformation expression * in @template T := TTLExp =: */ private boolean validTypeTransformationExpression(Node expr) { if (!isValidExpression(expr)) { warnInvalidExpression("type transformation", expr); return false; } if (isTypeVar(expr) || isTypeName(expr)) { return true; } // Check for valid keyword String name = getCallName(expr); if (!isValidKeyword(name)) { warnInvalidExpression("type transformation", expr); return false; } Keywords keyword = nameToKeyword(name); // Check the rest of the expression depending on the kind switch (keyword.kind) { case TYPE_CONSTRUCTOR: return validTypeExpression(expr); case OPERATION: return validOperationExpression(expr); default: throw new IllegalStateException("Invalid type transformation expression"); } } }
/** * A template type expression must be of the form type(typename, TTLExp,...) * or type(typevar, TTLExp...) */ private boolean validTemplateTypeExpression(Node expr) { // The expression must have at least three children the type keyword, // a type name (or type variable) and a type expression if (!checkParameterCount(expr, Keywords.TYPE)) { return false; } int paramCount = getCallParamCount(expr); // The first parameter must be a type variable or a type name Node firstParam = getCallArgument(expr, 0); if (!isTypeVar(firstParam) && !isTypeName(firstParam)) { warnInvalid("type name or type variable", expr); warnInvalidInside("template type operation", expr); return false; } // The rest of the parameters must be valid type expressions for (int i = 1; i < paramCount; i++) { if (!validTypeTransformationExpression(getCallArgument(expr, i))) { warnInvalidInside("template type operation", expr); return false; } } return true; }
private boolean validNativeTypeExpr(Node expr) { // The expression must have two children: // - The typeExpr keyword // - A string if (!checkParameterCount(expr, Keywords.TYPEEXPR)) { return false; } Node typeString = getCallArgument(expr, 0); if (!typeString.isString()) { warnInvalidExpression("native type", expr); warnInvalidInside(Keywords.TYPEEXPR.name, expr); return false; } Node typeExpr = JsDocInfoParser.parseTypeString(typeString.getString()); typeString.detach(); expr.addChildToBack(typeExpr); return true; }
private boolean validTypevarPredicate(Node expr, int paramCount) { // Each parameter must be valid string parameter for (int i = 0; i < paramCount; i++) { if (!validTypevarParam(getCallArgument(expr, i))) { warnInvalidInside("boolean", expr); return false; } } return true; }
new TypeTransformationParser(typeTransformationExpr, sourceFile, errorReporter, templateLineno, templateCharno); if (ttlParser.parseTypeTransformation() && !jsdocBuilder.recordTypeTransformation( names.get(0), ttlParser.getTypeTransformationAst())) { addTypeWarning( "msg.jsdoc.template.name.declared.twice", templateLineno, templateCharno);
/** * An all type expression must be of the form: all() */ private boolean validAllTypeExpression(Node expr) { // The expression must have no children return checkParameterCount(expr, Keywords.ALL); }
if (isBooleanOperation(expr)) { return validBooleanOperation(expr); if (!isOperation(expr)) { warnInvalidExpression("boolean", expr); return false; if (!isValidPredicate(getCallName(expr))) { warnInvalid("boolean predicate", expr); return false; Keywords keyword = nameToKeyword(getCallName(expr)); if (!checkParameterCount(expr, keyword)) { return false; return validTypePredicate(expr, getCallParamCount(expr)); case STRING_PREDICATE: return validStringPredicate(expr, getCallParamCount(expr)); case TYPEVAR_PREDICATE: return validTypevarPredicate(expr, getCallParamCount(expr)); default: throw new IllegalStateException("Invalid boolean expression");
if (!checkParameterCount(expr, Keywords.MAPRECORD)) { return false; if (!validTypeTransformationExpression(getCallArgument(expr, 0))) { warnInvalidInside(Keywords.MAPRECORD.name, getCallArgument(expr, 0)); return false; if (!getCallArgument(expr, 1).isFunction()) { warnInvalid("map function", getCallArgument(expr, 1)); warnInvalidInside(Keywords.MAPRECORD.name, getCallArgument(expr, 1)); return false; Node mapFn = getCallArgument(expr, 1); int mapFnParamCount = getFunctionParamCount(mapFn); if (mapFnParamCount < 2) { warnMissingParam("map function", mapFn); warnInvalidInside(Keywords.MAPRECORD.name, getCallArgument(expr, 1)); return false; warnExtraParam("map function", mapFn); warnInvalidInside(Keywords.MAPRECORD.name, getCallArgument(expr, 1)); return false; Node mapFnBody = getFunctionBody(mapFn); if (!validTypeTransformationExpression(mapFnBody)) { warnInvalidInside("map function body", mapFnBody); return false;
/** * A TTL type expression must be a union type, a template type, a record type * or any of the type predicates (none, rawTypeOf, templateTypeOf). */ private boolean validTypeExpression(Node expr) { String name = getCallName(expr); Keywords keyword = nameToKeyword(name); switch (keyword) { case TYPE: return validTemplateTypeExpression(expr); case UNION: return validUnionTypeExpression(expr); case NONE: return validNoneTypeExpression(expr); case ALL: return validAllTypeExpression(expr); case UNKNOWN: return validUnknownTypeExpression(expr); case RAWTYPEOF: return validRawTypeOfTypeExpression(expr); case TEMPLATETYPEOF: return validTemplateTypeOfExpression(expr); case RECORD: return validRecordTypeExpression(expr); case TYPEEXPR: return validNativeTypeExpr(expr); default: throw new IllegalStateException("Invalid type expression"); } }
/** * An operation expression is a cond or a mapunion */ private boolean validOperationExpression(Node expr) { String name = getCallName(expr); Keywords keyword = nameToKeyword(name); switch (keyword) { case COND: return validConditionalExpression(expr); case MAPUNION: return validMapunionExpression(expr); case MAPRECORD: return validMaprecordExpression(expr); case TYPEOFVAR: return validTypeOfVarExpression(expr); case INSTANCEOF: return validInstanceOfExpression(expr); case PRINTTYPE: return validPrintTypeExpression(expr); case PROPTYPE: return validPropTypeExpression(expr); default: throw new IllegalStateException("Invalid type transformation operation"); } }