The ad-hoc name resolution rule for `exports` forgets to check the
requested meaning. When `getTypeReferenceType` calls`
resolveTypeReferenceName` with `Type` only in order to give an error
when the program uses a value like a type, it is incorrectly able to
resolve `exports` instead of producing an error. Then this incorrect
symbol gets treated like an alias, which it isn't, causing the assert.
The fix, for now, is to make resolution of `exports` check the requested
meaning so that it only resolves when `Value` is requested. This makes
the above code an error ("Cannot use the namespace 'exports' as a
type."), but I think this is fine for a bug fix. We can decide later if
`exports` should behave like other expandos and be a legal type
reference.
Note that the name actually does resolve correctly, so JS users will get
the desired completions. They'll just have an error to suppress if they
have checkJs on.
`@constructor` put on anything incorrectly makes it a JS constructor. This
is a problem for actual constructors, because getJSClassType doesn't
work on actual classes. The fix is to make isJSConstructor require that
its declaration is a function.
JSDoc types references can often be to values, which can often be
circular in ways that types tied to declarations cannot. I decided to
create a separate property on SymbolLinks rather than reusing
declaredType, although I'm not sure that's strictly required.
In the binder, unreachable code mistakenly skips the `bindJSDoc` call in
`bindChildrenWorker`, which sets parent pointers. The fix is to call
`bindJSDoc` in the case of unreachable code as well.
* Skip asterisks after newline when parsing JSDoc types
* Single boolean expression
* Test for parsing and printing multiline function signatures with *
* check for expando initializers in resolveEntityName
when resolving type parameters in a prototype property assignment
declaration. For example, this already works:
```js
/** @template T */
function f(x) { this.x = x }
/** @returns {T} */
f.protototype.m = function () { return this.x }
```
This now works too:
```js
/** @template T */
var f = function (x) { this.x = x }
/** @returns {T} */
f.prototype.m = function () { return this.x }
```
Fixes#26826
* Lookup type parameters on prototype-assignment methods
In the same way that they're looked up on prototype-property methods.
That is, this previously worked:
```js
/** @template T */
function f() { }
/** @param {T} p */
f.prototype.m = function () { }
```
And this now works too:
```js
/** @template T */
function f() { }
f.prototype = {
/** @param {T} p */
m() { }
}
```
Note that the baselines still have errors; I'll file a followup bug for
them.
* Look up types on property assignments too
* Get [type] parameter types from @type tag
Previously only the return type was used in cases like this:
```js
/** @type {<T>(param?: T) => T | undefined} */
function g(param) {
return param;
}
```
Now the type parameters from the type tag are used, and the compiler
gets the type of the parameter by using the position in the signature of
the type tag.
Fixes#25618
* Fix split ifs according to PR comments
The assert is over-optimistic and should be removed until we can parse
every possible thing that people might put in a JSDoc type position.
Fixes#26693
* Fixes#26128 - signature comp for jsdoc @class.
Another issue caused by js functions tagged with jsdoc
`@constructor` not having construct signatures.
A jsdoc function type that constructs a type (`function(new: Ex)`),
has a construct signature and return value inferred as the
constructed type where as a jsdoc `@constructor` has no construct
signatures, and it's call signature has a void return type
(or undefined).
i.e:
```javascript
/** @constructor **/ function E() {};
// typeof E -> call signature: () => void
/** @param {function(new: E)} d */ function c(d) {}
// typeof d -> construct: () => E
```
--
This commit fixes this (in an inelegant way) by considering `@class` function signatures as construct signatures and synthesizing it's return value _only for signature comparison_.
There might be a slight performance hit, since the synthesized return value is not cached; but changing the `@class` function's return type in `getReturnTypeOfSignature` causes other issues.
* Update jsdoc function test to fix mistake.
* Allow type predicates
1. Parse type predicates. Note that they are parsed everywhere, and get
the appropriate error when used places besides a return type.
2. When creating a type predicate, correctly find the function's parameters
starting from the jsdoc return type.
* Fix type of TypePredicateNode.parent: add JSDocTypeExpression
* Update API baselines
* Handle JSDoc signature inside @type annotations
* Fix circularity when getting type predicates
Also move createTypePredicateFromTypePredicateNode closer to its use
* More cleanup based on review comments
* In JSDoc, resolve import types as values too
This is something that we probably should have been doing for some time.
Fixes#26049
* Fix whitespace lint
* Support the JSDoc @enum tag
`@enum` is used on a variable declaration with an object literal
initializer. It does a number of things:
1. The object literal has a closed set of properties, unlike other
object literals in Javascript.
2. The variable's name is resolvable as a type, but it just has the
declared type of the enum tag.
3. Each property's type must be assignable to the enum tag's declared type,
which can be any type.
For example,
```js
/** @enum {string} */
const Target = {
START: "START",
END: "END",
MISTAKE: 0, // error 'number' is not assignable to 'string' -- see (3)
}
Target.THIS_IS_AN_ERROR; // See (1)
/** @type {Target} See (2) */
var target = Target.START;
```
* Fix lint, add new test case, update API baselines
* Fix parsing of parenthesized JSDoc parameters
Parenthesis can start a jsdoc function parameter since it is just a
type, and parenthesis can start a type:
```js
/** @type {function(((string))): void} */
```
However, this is not legal in other parameter lists:
```ts
function x((((a))): string) { }
```
This change makes jsdoc function parameter lists parse differently than
normal parameter lists by allowing parenthesis as a start character of
jsdoc parameters.
* Parse nested uses of jsdoc function types
* Fix test
* Get return type from `@type` tag
This only happens in the checker, where the type is easily accessible.
The syntax-based check in getEffectiveReturnTypeNode as a fast path, and
for other uses that don't want to make a call to getTypeFromTypeNode.
Fixes#25525
* Implement PR suggestions
* Error when type tag isn't callable
* Fix lint
Block scoped variables, classes and enums would issue a bogus
use-before-def error in jsdoc because name resolution always adds Value,
even when resolving a type.
Fixes#25097
* get return type from `@type` tags
Previously, getJSDocReturnType did not check the `@type` tag for a type
node that has a return type. Now it does.
* Improve doc comment of getJSDocReturnType
* More type predicates in type guards!
* Update API baselines with new documentation (?!)
* Adds related spans and error grouping for duplicate identifier errors
* Trim trailing whitespace
* Record related info in error baselines
* Make error more whimsical
That is, only nest them if their name matches the provided parent name.
Otherwise do not nest them.
Note that this commit changes the behaviour of an incorrect typedef that
contains both an `@type` child tag and `@property` child tags.
Previously, the `@type` would be incorrectly nested under a `@property`
tag with type `object`, just like `@property` tags would be. Now, the
`@type` tag causes the entire typedef to ignore the `@property` tags and
treat the typedef as if it were an instance of the
typedef-and-nested-type pattern:
```js
/**
* @typedef {Object} name
* @type {{ the, actual, type }}
*/
```
* getDeclarationIdentifier handles undefined name
getNameOfDeclaration actually doesn't handle all declarations, only
those that produce names that could be reasonably used as an identifier.
Until now, getDeclarationIdentifier assumed that getNameOfDeclaration
always returned a name. This caused crashes whenever we tried to get the
name of something like a Constructor.
* Add test and baselines
* getNameOfDeclaration can return undefined
This requires all callers to handle it, which turns out now to be too
disruptive.
* Fix lint
* Check extends tag first in getClassExtendsHeritageClauseElement
Previously getBaseTypeNodeOfClass checked, but this is only used in a
few places.
* Fix names and add test
* Update API baseline
* Move jsdocAugments tests to conformance/jsdoc
* Better naming in checkClassLikeDeclaration
* Parse (and mostly support) template tag constraints
A bunch of tests hit the asserts I added though.
* Messy version is finished. Need to add a few tests
* Refactor to be smaller
* Small refactor + Add one test
* Another test
* Minor cleanup
* Fix error reporting on type parameters on ctors
* Simplify syntax of `@template` tag
This is a breaking change, but in my sample, nobody except webpack used the
erroneous syntax. I need to improve the error message, so
jsdocTemplateTag3 currently fails to remind me of that.
* Better error message for template tag
* Fix fourslash baselines
* Another fourslash update
* Address PR comments
* Simplify getEffectiveTypeParameterDeclarations
Make checkGrammarConstructorTypeParameters do a little more work
* Callback tag:Disallow nested-object-param syntax
Previously this caused a crash in parsing. If/when we want to support
this syntax, we will need to fix this crash.
* Update baselines
* Fix JSDoc type resolution
Breaks type parameter resolution that is looked up through prototype
methods, though. I need to fix that still.
* Check for prototype method assignments first
* Undo dedupe changes to getJSDocTags
* JS Type aliases can't refer to host type params
Previously, js type aliases (@typedef and @callback) could refer to
type paremeters defined in @template tags in a *different* jsdoc tag, as
long as both tags were hosted on the same signature.
* Reduce dedupe changes+update baseline
The only reason I had undone them was to merge successfully with an
older state of master.
* Add initial tests
* Add types
* Half of parsing (builds but does not pass tests)
* Parsing done; types are uglier; doesn't crash but doesn't pass
* Bind callback tag
Builds but tests still don't pass
* Only bind param tags inside callback tags
* Fix binding switch to only handle param tags once
* Checking is 1/3 done or so.
Now I'm going to go rename some members to be more uniform. I hate
unnnecessary conditionals.
* Rename typeExpression to type (for some jsdoc)
(maybe I'll rename more later)
* Rename the rest of typeExpressions
Turns out there is a constraint in services such that they all need to
be named the same.
* Few more checker changes
* Revert "Rename the rest of typeExpressions"
This reverts commit f41a96b24d.
* Revert "Rename typeExpression to type (for some jsdoc)"
This reverts commit 7d2233a00e.
* Finish undoing typeExpression rename
* Rename and improve getTypeParametersForAliasSymbol
Plus some other small fixes
* Core checking works, but is flabbergastingly messy
I'm serious.
* Callback return types work now
* Fix crash in services
* Make github diff smaller
* Try to make github diff even smaller
* Fix rename for callback tag
* Fix nav bar for callback tag
Also clean up some now-redundant code there to find the name of typedefs.
* Handle ooorder callback tags
Also get rid of redundant typedef name code *in the binder*. It's
everywhere!
* Add ooorder callback tag test
* Parse comments for typedef/callback+display param comments
* Always export callbacks
This requires almost no new code since it is basically the same as
typedefs
* Update baselines
* Fix support for nested namespaced callbacks
And add test
* Callbacks support type parameters
1. Haven't run it with all tests
2. Haven't tested typedef tags yet
3. Still allows shared symbols when on function or class declarations.
* Template tags are now bound correctly
* Test oorder template tags
It works.
* Parser cleanup
* Cleanup types and utilities
As much as possible, and not as much as I would like.
* Handle callback more often in services
* Cleanup of binder and checker
* More checker cleanup
* Remove TODOs and one more cleanup
* Support parameter-less callback tags
* Remove extra bind call on template type parameters
* Bind template tag containers
Doesn't quite work with typedefs, but that's because it's now stricter,
without the typedef fixes. I'm going to merge with jsdoc/callback and
see how it goes.
* Fix fourslash failures
* Stop pre-binding js type aliases
Next up, stop pre-binding js type parameters
* Further cleanup of delayed js type alias binding
* Stop prebinding template tags too
This gets rid of prebinding entirely
* Remove TODO
* Fix lint
* Finish merge with use-jsdoc-aliases
* Update callback tag baselines
* Rename getTypeParametersForAliasSymbol
The real fix is *probably* to rename Type.aliasTypeArguments to
aliasTypeParameters, but I want to make sure and then put it in a
separate PR.
* No error for require
Still errors for module and exports, and require's type is now
incorreclty 'any'; I broke module resolution somehow. Needs
investigation.
* module/exports symbols+update isCommonJsRequire
Everything passes the tests but the code can be improved
* Update baselines
* Cleanup
* Update baselines of new tests
* Get rid of exports symbol
It wasn't doing anything anyway.
* Always export typedefs
This actually just required deleting a check in declareModuleMembers
and checking for external AND commonjs modules in a couple of places.
However, while experimenting with this feature, I discovered that even
previously-exported typedefs would only be exported if they came after a
commonjs export node. So I added a commonjs check to the pass in the
parser. It will not catch nested module.exports, but it will catch
top-level assignments.
The new test tests both changes.
* Post-bind typedef instead of pre-checking for commonjs
* Duplicate identifier errors
* Fix class type reference resolution+update baselines
* Move to a type-based check for duplicate identifiers
* Add prettier and fix crash bug
Name resolution would crash when resolving a type name inside a
typedef's property tag.
* Update tsconfig and thefore prettier baseline
* Make `module.export =` an alias like `export=` is
This breaks a couple of tests for previous workarounds. Fix in upcoming
commits.
* Basically fixes all the breaks, but needs cleanup
* More notes to myself
* Clean up TODOs
* Call mergeSymbolTable and delete export= afterward
instead of basically copying the code myself.
* More cleanup
* Remove unnecessary check in import type checking
* Revert to DIY code.
It is more correct and will go away in a few days.
* Exported class expressions can be used as type
In both JS and TS
* Do not require named class expressions
* Support @template as a class type parameter
Still need to do the following:
1. Correctly get jsdoc host in predicate.
2. Make this work for constructor functions too.
3. Scan rest of codebase for other usages of the type parameters
property that should be calls to getEffectiveTypeParameterDeclarations.
4. Rename tp to something more readable, like typar or ts'.
* Use jsdoc host declaration to find container
* Longer names for type parameters
* Fix renaming operation
* Update fourslash test
* Support @template for JS constructors
* Look for both outer and tag type parameters
* Improve naming to improve code clarity
* JSDoc:positional matching of destructured params
1. When looking up tags for a parameter whose name is a binding pattern, use
the index of the parameter to get the type.
2. When reporting errors for `@param` tags with no matching parameter
name, do not report the error for tags whose index in the `@param` tag list
matches the index of a parameter whose name is a binding pattern.
* Change to an assert
* Improve comment text
* Correctly parse JSDoc type *=
* Allow `markdown` quoted param names in JSDoc
* Add tests and update baselines
* Get correct span for the type '*'
* Fix whitespace lint
* Add unbracketed type test
* Fix type when annotated with a JSDoc function type
Previously,
1. A variable annotated with a JSDoc function type would not require all
its parameters to be provided. This should only apply to functions
without a type annotation.
2. A parameter in a function with a JSDoc function type annotation would
still have the type 'any'.
3. Two `var` declarations in a Typescript and Javascript file,
respectively, would error even when they had identical function types.
* Update baselines and add constructor test
* Handle ConstructorType too
* Add test:method sig inside literal type
* Contextually type parameters by parent sig's JSDoc
Instead of a syntactic check in getJSDocTag
* Remove redundant check:isUntypedSignatureInJSFile
* Positive check for value signatures
Instead of excluding type signatures piecemeal.
* Parse JSDoc ...T and T= only at top-level JSDoc
...T and T= should only be legal at the top level of a type, and only in
JSDoc, since at least T= is ambiguous elsewhere. This PR changes parsing
to make that happen. The resulting parse tree is now simpler, allowing
me to get rid of some code I had to add in the checker.
* Extract JSDoc type parsing into its own function
* PR comments:return from parseJSDocType