Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 11 additions & 24 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3257,9 +3257,6 @@ func (c *Checker) checkFunctionOrMethodDeclaration(node *ast.Node) {
if c.getContextualCallSignature(c.getTypeFromTypeNode(node.FunctionLikeData().FullSignature), node) == nil {
c.error(node.FunctionLikeData().FullSignature, diagnostics.A_JSDoc_type_tag_on_a_function_must_have_a_signature_with_the_correct_number_of_arguments)
}
if node.Type() != nil || core.Some(node.Parameters(), func(p *ast.Node) bool { return p.Type() != nil }) {
c.error(node.FunctionLikeData().FullSignature, diagnostics.A_JSDoc_type_tag_may_not_occur_with_a_param_or_returns_tag)
}
}
if node.Type() == nil {
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
Expand Down Expand Up @@ -9830,9 +9827,6 @@ func (c *Checker) checkFunctionExpressionOrObjectLiteralMethod(node *ast.Node, c
if c.getContextualCallSignature(c.getTypeFromTypeNode(node.FunctionLikeData().FullSignature), node) == nil {
c.error(node.FunctionLikeData().FullSignature, diagnostics.A_JSDoc_type_tag_on_a_function_must_have_a_signature_with_the_correct_number_of_arguments)
}
if node.Type() != nil || core.Some(node.Parameters(), func(p *ast.Node) bool { return p.Type() != nil }) {
c.error(node.FunctionLikeData().FullSignature, diagnostics.A_JSDoc_type_tag_may_not_occur_with_a_param_or_returns_tag)
}
}
c.contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node, checkMode)
return c.getTypeOfSymbol(c.getSymbolOfDeclaration(node))
Expand Down Expand Up @@ -11678,12 +11672,11 @@ func (c *Checker) TryGetThisTypeAtEx(node *ast.Node, includeGlobalThis bool, con
container = c.getThisContainer(node, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/)
}
if ast.IsFunctionLike(container) && (!c.isInParameterInitializerBeforeContainingFunction(node) || ast.GetThisParameter(container) != nil) {
thisType := c.getThisTypeOfDeclaration(container)
if thisType == nil && ast.IsInJSFile(container) {
if sig := c.getSignatureOfFullSignatureType(container); sig != nil {
thisType = c.getThisTypeOfSignature(sig)
}
sig := c.getSignatureOfFullSignatureType(container)
if sig == nil {
sig = c.getSignatureFromDeclaration(container)
}
thisType := c.getThisTypeOfSignature(sig)
// Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated.
// If this is a function in a JS file, it might be a class method.
if thisType == nil {
Expand Down Expand Up @@ -11782,10 +11775,6 @@ func (c *Checker) isInParameterInitializerBeforeContainingFunction(node *ast.Nod
return false
}

func (c *Checker) getThisTypeOfDeclaration(declaration *ast.Node) *Type {
return c.getThisTypeOfSignature(c.getSignatureFromDeclaration(declaration))
}

func (c *Checker) checkThisInStaticClassFieldInitializerInDecoratedClass(thisExpression *ast.Node, container *ast.Node) {
if ast.IsPropertyDeclaration(container) && ast.HasStaticModifier(container) && c.legacyDecorators {
initializer := container.Initializer()
Expand Down Expand Up @@ -19091,11 +19080,11 @@ func (c *Checker) getSignaturesOfSymbol(symbol *ast.Symbol) []*Signature {
}
// If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters.
// Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would suppress checks that the two are compatible.
if sig := c.getSignatureOfFullSignatureType(decl); sig != nil {
result = append(result, sig)
continue
sig := c.getSignatureOfFullSignatureType(decl)
if sig == nil {
sig = c.getSignatureFromDeclaration(decl)
}
result = append(result, c.getSignatureFromDeclaration(decl))
result = append(result, sig)
}
return result
}
Expand Down Expand Up @@ -19177,15 +19166,13 @@ func (c *Checker) getSignatureFromDeclaration(declaration *ast.Node) *Signature
}

func (c *Checker) getTypeParametersFromDeclaration(declaration *ast.Node) []*Type {
if sig := c.getSignatureOfFullSignatureType(declaration); sig != nil {
return sig.TypeParameters()
}
var result []*Type
for _, node := range declaration.TypeParameters() {
result = core.AppendIfUnique(result, c.getDeclaredTypeOfTypeParameter(node.Symbol()))
}
if len(result) == 0 && ast.IsFunctionDeclaration(declaration) {
if sig := c.getSignatureOfFullSignatureType(declaration); sig != nil {
return sig.TypeParameters()
}
}
return result
}

Expand Down
8 changes: 0 additions & 8 deletions internal/checker/relater.go
Original file line number Diff line number Diff line change
Expand Up @@ -1994,19 +1994,11 @@ func (c *Checker) getTypePredicateOfSignature(sig *Signature) *TypePredicate {
default:
if sig.declaration != nil {
typeNode := sig.declaration.Type()
var jsdocTypePredicate *TypePredicate
if typeNode == nil {
if jsdocSignature := c.getSignatureOfFullSignatureType(sig.declaration); jsdocSignature != nil {
jsdocTypePredicate = c.getTypePredicateOfSignature(jsdocSignature)
}
}
switch {
case typeNode != nil:
if ast.IsTypePredicateNode(typeNode) {
sig.resolvedTypePredicate = c.createTypePredicateFromTypePredicateNode(typeNode, sig)
}
case jsdocTypePredicate != nil:
sig.resolvedTypePredicate = jsdocTypePredicate
case ast.IsFunctionLikeDeclaration(sig.declaration) && (sig.resolvedReturnType == nil || sig.resolvedReturnType.flags&TypeFlagsBoolean != 0) && c.getParameterCount(sig) > 0:
sig.resolvedTypePredicate = c.noTypePredicate // avoid infinite loop
sig.resolvedTypePredicate = c.getTypePredicateFromBody(sig.declaration)
Expand Down
2 changes: 0 additions & 2 deletions internal/diagnostics/diagnostics_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions internal/diagnostics/extraDiagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
"category": "Error",
"code": 8030
},
"A JSDoc '@type' tag may not occur with a '@param' or '@returns' tag.": {
"category": "Error",
"code": 8040
},
"Failed to delete file '{0}'.": {
"category": "Message",
"code": 6353
Expand Down
8 changes: 4 additions & 4 deletions internal/parser/reparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
}
if fun, ok := getFunctionLikeHost(parent); ok {
noTypedParams := core.Every(fun.Parameters(), func(param *ast.Node) bool { return param.Type() == nil })
if fun.Type() == nil && noTypedParams && tag.AsJSDocTypeTag().TypeExpression != nil {
if fun.TypeParameterList() == nil && fun.Type() == nil && noTypedParams && tag.AsJSDocTypeTag().TypeExpression != nil {
fun.FunctionLikeData().FullSignature = p.factory.DeepCloneReparse(tag.AsJSDocTypeTag().TypeExpression.Type())
p.finishMutatedNode(fun)
}
Expand Down Expand Up @@ -389,7 +389,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
}
case ast.KindJSDocTemplateTag:
if fun, ok := getFunctionLikeHost(parent); ok {
if fun.TypeParameters() == nil {
if fun.TypeParameters() == nil && fun.FunctionLikeData().FullSignature == nil {
fun.FunctionLikeData().TypeParameters = p.gatherTypeParameters(jsDoc, nil /*tagWithTypeParameters*/)
p.finishMutatedNode(fun)
}
Expand All @@ -407,7 +407,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
}
}
case ast.KindJSDocParameterTag:
if fun, ok := getFunctionLikeHost(parent); ok {
if fun, ok := getFunctionLikeHost(parent); ok && fun.FunctionLikeData().FullSignature == nil {
parameterTag := tag.AsJSDocParameterOrPropertyTag()
if param, ok := findMatchingParameter(fun, parameterTag, jsDoc); ok {
if param.Type == nil && parameterTag.TypeExpression != nil {
Expand Down Expand Up @@ -449,7 +449,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
}
}
case ast.KindJSDocReturnTag:
if fun, ok := getFunctionLikeHost(parent); ok {
if fun, ok := getFunctionLikeHost(parent); ok && fun.FunctionLikeData().FullSignature == nil {
if fun.Type() == nil && tag.AsJSDocReturnTag().TypeExpression != nil {
fun.FunctionLikeData().Type = p.factory.DeepCloneReparse(tag.AsJSDocReturnTag().TypeExpression.Type())
p.finishMutatedNode(fun)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,44 +1,126 @@
//// [tests/cases/conformance/jsdoc/jsdocTypeParameterTagConflict.ts] ////

//// [a.js]
// @type on a function is applicable when there are no preceding @param, @return, or @template annotations
// and no @type parameter annotations.

// @param for a parameter is applicable when there is no applicable @type annotation for the function and
// no @type annotation on the parameter.

// @return is applicable when there is no applicable @type annotation for the function.

// @template is applicable when there is no applicable @type annotation for the function.

/**
* @type {(a: 1) => true}
* @param {2} a
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
* @return {string}
*/
export function conflictingParam(a) { return true }
function f1(/** @type {5}*/ a, b) { return "abc" }

/**
* @type {(b: 3) => true}
* @return {false}
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
* @return {string}
*/
export function conflictingReturn(b) { return false }
function f2(a, b) { return 42 }

/**
* @param {3} a
* @type {(a: 1, b: 2) => number}
* @param {4} b
* @return {string}
*/
function f3(a, b) { return "abc" }

/**
* @return {string}
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
*/
function f4(a, b) { return "abc" }

/**
* @type {(a: 1, b: 2) => number}
* @template T
* @template U
* @param {T} a
* @param {U} b
* @return {string}
*/
function f5(a, b) { return 42 }

/**
* @type {(c: 4) => true}
* @param {5} d
* @return {false}
* @template T
* @type {(a: 1, b: 2) => number}
* @template U
* @param {T} a
* @param {U} b
* @return {string}
*/
export function conflictingBoth(d) { return false }
function f6(a, b) { return "abc" }

/**
* @param {1} a
* @param {2} a
*/
function f7(a) {}




//// [a.d.ts]
/**
* @type {(a: 1) => true}
* @param {2} a
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
* @return {string}
*/
export declare function conflictingParam(a: 2): true;
declare function f1(/** @type {5}*/ a: 5, b: 4): string;
/**
* @type {(b: 3) => true}
* @return {false}
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
* @return {string}
*/
export declare function conflictingReturn(b: 3): false;
declare function f2(a: 1, b: 2): number;
/**
* @type {(c: 4) => true}
* @param {5} d
* @return {false}
* @param {3} a
* @type {(a: 1, b: 2) => number}
* @param {4} b
* @return {string}
*/
declare function f3(a: 3, b: 4): string;
/**
* @return {string}
* @type {(a: 1, b: 2) => number}
* @param {3} a
* @param {4} b
*/
declare function f4(a: 3, b: 4): string;
/**
* @type {(a: 1, b: 2) => number}
* @template T
* @template U
* @param {T} a
* @param {U} b
* @return {string}
*/
declare function f5(a: 1, b: 2): number;
/**
* @template T
* @type {(a: 1, b: 2) => number}
* @template U
* @param {T} a
* @param {U} b
* @return {string}
*/
declare function f6<T, U>(a: T, b: U): string;
/**
* @param {1} a
* @param {2} a
*/
export declare function conflictingBoth(d: 5): false;
declare function f7(a: 1): void;
Loading
Loading