use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.
the class CheckMissingOverrideTypes method recordMissingParamAnnotations.
private void recordMissingParamAnnotations(Node fnNode, JSDocInfo jsDoc, FunctionType fnType, JSDocInfo.Builder builder) {
checkState(fnNode.isFunction(), fnNode);
Set<String> jsDocParamNames = jsDoc.getParameterNames();
List<String> astParamNames = getFunctionParamNamesOrPlaceholder(fnNode);
List<Parameter> fnTypeParams = fnType.getParameters();
for (int paramIndex = 0; paramIndex < astParamNames.size(); paramIndex++) {
String astName = astParamNames.get(paramIndex);
if (jsDocParamNames.contains(astName)) {
continue;
}
// missing annotation for `paramName`
Parameter fnTypeParam = fnTypeParams.get(paramIndex);
JSType paramType = fnTypeParam.getJSType();
if (fnTypeParam.isOptional()) {
paramType = paramType.restrictByNotUndefined();
}
Node paramTypeAst = typeToTypeAst(paramType);
if (fnTypeParam.isOptional()) {
paramTypeAst = new Node(Token.EQUALS, paramTypeAst);
}
builder.recordParameter(astName, new JSTypeExpression(paramTypeAst, JSDOC_FILE_NAME));
}
}
use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.
the class ClosureRewriteClass method mergeJsDocFor.
/**
* Merges the JSDoc from the class and constructor into a single function-level JSDoc
*
* @param includeConstructorExport if false, disregards the @export JSDoc from the constructor, if
* any. This is a workaround for b/138324343.
*/
private JSDocInfo mergeJsDocFor(ClassDefinition cls, Node associatedNode, boolean includeConstructorExport) {
// avoid null checks
JSDocInfo classInfo = (cls.classInfo != null) ? cls.classInfo : JSDocInfo.builder().parseDocumentation().build(true);
JSDocInfo ctorInfo = (cls.constructor.info != null) ? cls.constructor.info : JSDocInfo.builder().parseDocumentation().build(true);
Node superNode = cls.superClass;
// Start with a clone of the constructor info if there is one.
JSDocInfo.Builder mergedInfo = cls.constructor.info != null ? JSDocInfo.Builder.copyFrom(ctorInfo) : JSDocInfo.builder().parseDocumentation();
// TODO(b/138324343): remove this case (or, even better, just delete goog.defineClass support).
if (!includeConstructorExport && ctorInfo.isExport()) {
mergedInfo.removeExport();
}
// merge block description
String blockDescription = Joiner.on("\n").skipNulls().join(classInfo.getBlockDescription(), ctorInfo.getBlockDescription());
if (!blockDescription.isEmpty()) {
mergedInfo.recordBlockDescription(blockDescription);
}
// merge suppressions
Set<String> suppressions = new HashSet<>();
suppressions.addAll(classInfo.getSuppressions());
suppressions.addAll(ctorInfo.getSuppressions());
if (!suppressions.isEmpty()) {
mergedInfo.recordSuppressions(suppressions);
}
// Use class deprecation if set.
if (classInfo.isDeprecated()) {
mergedInfo.recordDeprecated();
}
String deprecationReason = null;
if (classInfo.getDeprecationReason() != null) {
deprecationReason = classInfo.getDeprecationReason();
mergedInfo.recordDeprecationReason(deprecationReason);
}
// Use class visibility if specifically set
Visibility visibility = classInfo.getVisibility();
if (visibility != null && visibility != JSDocInfo.Visibility.INHERITED) {
mergedInfo.recordVisibility(classInfo.getVisibility());
}
if (classInfo.isAbstract()) {
mergedInfo.recordAbstract();
}
if (classInfo.isConstant()) {
mergedInfo.recordConstancy();
}
if (classInfo.isExport()) {
mergedInfo.recordExport();
}
// If @ngInject is on the ctor, it's already been copied above.
if (classInfo.isNgInject()) {
compiler.report(JSError.make(associatedNode, GOOG_CLASS_NG_INJECT_ON_CLASS));
mergedInfo.recordNgInject(true);
}
if (classInfo.makesUnrestricted() || ctorInfo.makesUnrestricted()) {
mergedInfo.recordUnrestricted();
} else if (classInfo.makesDicts() || ctorInfo.makesDicts()) {
mergedInfo.recordDict();
} else {
// @struct by default
mergedInfo.recordStruct();
}
// @constructor is implied, @interface must be explicit
boolean isInterface = classInfo.isInterface() || ctorInfo.isInterface();
if (isInterface) {
if (classInfo.usesImplicitMatch() || ctorInfo.usesImplicitMatch()) {
mergedInfo.recordImplicitMatch();
} else {
mergedInfo.recordInterface();
}
List<JSTypeExpression> extendedInterfaces = null;
if (classInfo.getExtendedInterfacesCount() > 0) {
extendedInterfaces = classInfo.getExtendedInterfaces();
} else if (ctorInfo.getExtendedInterfacesCount() == 0 && superNode != null) {
extendedInterfaces = ImmutableList.of(getSuperclassFor(superNode));
}
if (extendedInterfaces != null) {
for (JSTypeExpression extend : extendedInterfaces) {
mergedInfo.recordExtendedInterface(extend);
}
}
} else {
// @constructor by default
mergedInfo.recordConstructor();
if (classInfo.getBaseType() != null) {
mergedInfo.recordBaseType(classInfo.getBaseType());
} else if (superNode != null) {
// a "super" implies @extends, build a default.
JSTypeExpression baseType = getSuperclassFor(superNode);
mergedInfo.recordBaseType(baseType);
}
// @implements from the class if they exist
List<JSTypeExpression> interfaces = classInfo.getImplementedInterfaces();
for (JSTypeExpression implemented : interfaces) {
mergedInfo.recordImplementedInterface(implemented);
}
}
// merge @template types if they exist
ImmutableMap<String, JSTypeExpression> classTemplates = classInfo.getTemplateTypes();
ImmutableMap<String, JSTypeExpression> ctorTemplates = ctorInfo.getTemplateTypes();
for (Map.Entry<String, JSTypeExpression> entry : classTemplates.entrySet()) {
mergedInfo.recordTemplateTypeName(entry.getKey(), entry.getValue());
}
for (Map.Entry<String, JSTypeExpression> entry : ctorTemplates.entrySet()) {
mergedInfo.recordTemplateTypeName(entry.getKey(), entry.getValue());
}
return mergedInfo.build();
}
use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.
the class CheckGlobalThis method shouldTraverse.
/**
* Since this pass reports errors only when a global {@code this} keyword
* is encountered, there is no reason to traverse non global contexts.
*/
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
if (n.isFunction()) {
// is the global "this", not an instance of Foo.
if (n.isArrowFunction()) {
return true;
}
// Don't traverse functions that are constructors or have the @this
// or @override annotation.
JSDocInfo jsDoc = NodeUtil.getBestJSDocInfo(n);
if (jsDoc != null && (jsDoc.isConstructor() || jsDoc.isInterface() || jsDoc.hasThisType() || jsDoc.isOverride())) {
return false;
}
if (jsDoc != null) {
JSTypeExpression functionType = jsDoc.getType();
if (functionType != null) {
Node functionNode = functionType.getRoot();
if (functionNode != null && functionNode.isFunction()) {
// function(this: ThisType, ...)
// `this:` is only allowed as the very first child of the
// FUNCTION node.
Node thisNode = functionNode.getFirstChild();
if (thisNode != null && thisNode.isThis()) {
// Type of `this` is specified, so no need to check further.
return false;
}
}
}
}
// Don't traverse functions unless they would normally
// be able to have a @this annotation associated with them. e.g.,
// var a = function() { }; // or
// function a() {} // or
// a.x = function() {}; // or
// var a = {x: function() {}};
Token pType = parent.getToken();
if (!(pType == Token.BLOCK || pType == Token.SCRIPT || pType == Token.NAME || pType == Token.ASSIGN || // object literal keys
pType == Token.STRING_KEY)) {
return false;
}
// Don't traverse functions that are getting lent to a prototype.
Node grandparent = parent.getParent();
if (NodeUtil.mayBeObjectLitKey(parent)) {
JSDocInfo maybeLends = grandparent.getJSDocInfo();
if (maybeLends != null && maybeLends.hasLendsName() && maybeLends.getLendsName().getRoot().getString().endsWith(".prototype")) {
return false;
}
}
}
if (parent != null && parent.isAssign()) {
Node lhs = parent.getFirstChild();
if (n == lhs) {
// assignLhsChild should not be overridden.
if (assignLhsChild == null) {
assignLhsChild = lhs;
}
} else {
// property or subproperty.
if (NodeUtil.isNormalGet(lhs)) {
if (lhs.isGetProp() && lhs.getString().equals("prototype")) {
return false;
}
Node llhs = lhs.getFirstChild();
if (llhs.isGetProp() && llhs.getString().equals("prototype")) {
return false;
}
}
}
}
return true;
}
use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.
the class CheckMissingRequires method visitJsDocInfo.
private void visitJsDocInfo(NodeTraversal t, ModuleMetadata currentModule, JSDocInfo info) {
// Collect template parameter names before checking, so that annotations on the same node that
// reference the name are excluded from the check.
templateParamNames.addAll(info.getTemplateTypeNames());
templateParamNames.addAll(info.getTypeTransformations().keySet());
if (info.hasType()) {
visitJsDocExpr(t, currentModule, info.getType(), /* isStrongReference */
false);
}
for (String param : info.getParameterNames()) {
if (info.hasParameterType(param)) {
visitJsDocExpr(t, currentModule, info.getParameterType(param), /* isStrongReference=*/
false);
}
}
if (info.hasReturnType()) {
visitJsDocExpr(t, currentModule, info.getReturnType(), /* isStrongReference=*/
false);
}
if (info.hasEnumParameterType()) {
visitJsDocExpr(t, currentModule, info.getEnumParameterType(), /* isStrongReference=*/
false);
}
if (info.hasTypedefType()) {
visitJsDocExpr(t, currentModule, info.getTypedefType(), /* isStrongReference=*/
false);
}
if (info.hasThisType()) {
visitJsDocExpr(t, currentModule, info.getThisType(), /* isStrongReference=*/
false);
}
if (info.hasBaseType()) {
// Note that `@extends` requires a goog.require, not a goog.requireType.
visitJsDocExpr(t, currentModule, info.getBaseType(), /* isStrongReference=*/
true);
}
for (JSTypeExpression expr : info.getExtendedInterfaces()) {
// Note that `@extends` requires a goog.require, not a goog.requireType.
visitJsDocExpr(t, currentModule, expr, /* isStrongReference=*/
true);
}
for (JSTypeExpression expr : info.getImplementedInterfaces()) {
// Note that `@implements` requires a goog.require, not a goog.requireType.
visitJsDocExpr(t, currentModule, expr, /* isStrongReference=*/
true);
}
}
use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.
the class CheckJSDocStyle method checkInlineParams.
/**
* Checks that the inline type annotations are correct.
*/
private void checkInlineParams(NodeTraversal t, Node function, JSDocInfo fnJSDoc) {
Node paramList = NodeUtil.getFunctionParameters(function);
for (Node param = paramList.getFirstChild(); param != null; param = param.getNext()) {
JSDocInfo jsDoc = param.isDefaultValue() ? param.getFirstChild().getJSDocInfo() : param.getJSDocInfo();
if (jsDoc == null) {
compiler.report(JSError.make(param, MISSING_PARAMETER_JSDOC, fnJSDoc != null && fnJSDoc.isOverride() ? "" : ""));
return;
} else {
JSTypeExpression paramType = jsDoc.getType();
checkNotNull(paramType, "Inline JSDoc info should always have a type");
checkParam(t, param, null, paramType);
}
}
}
Aggregations