mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add callback tag, with type parameters (#23947)
* 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 commitf41a96b24d. * Revert "Rename typeExpression to type (for some jsdoc)" This reverts commit7d2233a00e. * 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.
This commit is contained in:
+75
-88
@@ -118,7 +118,7 @@ namespace ts {
|
||||
let thisParentContainer: Node; // Container one level up
|
||||
let blockScopeContainer: Node;
|
||||
let lastContainer: Node;
|
||||
let delayedTypedefs: { typedef: JSDocTypedefTag, container: Node, lastContainer: Node, blockScopeContainer: Node, parent: Node }[];
|
||||
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag)[];
|
||||
let seenThisKeyword: boolean;
|
||||
|
||||
// state used by control flow analysis
|
||||
@@ -188,7 +188,7 @@ namespace ts {
|
||||
thisParentContainer = undefined;
|
||||
blockScopeContainer = undefined;
|
||||
lastContainer = undefined;
|
||||
delayedTypedefs = undefined;
|
||||
delayedTypeAliases = undefined;
|
||||
seenThisKeyword = false;
|
||||
currentFlow = undefined;
|
||||
currentBreakTarget = undefined;
|
||||
@@ -273,6 +273,7 @@ namespace ts {
|
||||
return InternalSymbolName.Constructor;
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
return InternalSymbolName.Call;
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
@@ -301,9 +302,6 @@ namespace ts {
|
||||
const functionType = <JSDocFunctionType>node.parent;
|
||||
const index = functionType.parameters.indexOf(node as ParameterDeclaration);
|
||||
return "arg" + index as __String;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
const name = getNameOfJSDocTypedef(node as JSDocTypedefTag);
|
||||
return typeof name !== "undefined" ? name.escapedText : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,8 +454,8 @@ namespace ts {
|
||||
// during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation
|
||||
// and this case is specially handled. Module augmentations should only be merged with original module definition
|
||||
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
|
||||
if (node.kind === SyntaxKind.JSDocTypedefTag) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefTag(node)) {
|
||||
if (isJSDocTypeAlias(node)) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) {
|
||||
if (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) {
|
||||
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
|
||||
}
|
||||
@@ -628,22 +626,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindChildrenWorker(node: Node): void {
|
||||
// Binding of JsDocComment should be done before the current block scope container changes.
|
||||
// because the scope of JsDocComment should not be affected by whether the current node is a
|
||||
// container or not.
|
||||
if (hasJSDocNodes(node)) {
|
||||
if (isInJavaScriptFile(node)) {
|
||||
for (const j of node.jsDoc) {
|
||||
bind(j);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const j of node.jsDoc) {
|
||||
setParentPointers(node, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkUnreachable(node)) {
|
||||
bindEachChild(node);
|
||||
return;
|
||||
@@ -709,11 +691,9 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
bindCallExpressionFlow(<CallExpression>node);
|
||||
break;
|
||||
case SyntaxKind.JSDocComment:
|
||||
bindJSDocComment(<JSDoc>node);
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
bindJSDocTypedefTag(<JSDocTypedefTag>node);
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
break;
|
||||
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
|
||||
case SyntaxKind.SourceFile:
|
||||
@@ -728,6 +708,7 @@ namespace ts {
|
||||
bindEachChild(node);
|
||||
break;
|
||||
}
|
||||
bindJSDoc(node);
|
||||
}
|
||||
|
||||
function isNarrowingExpression(expr: Expression): boolean {
|
||||
@@ -1379,24 +1360,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindJSDocComment(node: JSDoc) {
|
||||
forEachChild(node, n => {
|
||||
if (n.kind !== SyntaxKind.JSDocTypedefTag) {
|
||||
bind(n);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindJSDocTypedefTag(node: JSDocTypedefTag) {
|
||||
forEachChild(node, n => {
|
||||
// if the node has a fullName "A.B.C", that means symbol "C" was already bound
|
||||
// when we visit "fullName"; so when we visit the name "C" as the next child of
|
||||
// the jsDocTypedefTag, we should skip binding it.
|
||||
if (node.fullName && n === node.name && node.fullName.kind !== SyntaxKind.Identifier) {
|
||||
return;
|
||||
}
|
||||
bind(n);
|
||||
});
|
||||
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) {
|
||||
if (node.fullName) {
|
||||
setParentPointers(node, node.fullName);
|
||||
}
|
||||
}
|
||||
|
||||
function bindCallExpressionFlow(node: CallExpression) {
|
||||
@@ -1456,6 +1423,7 @@ namespace ts {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
@@ -1545,6 +1513,7 @@ namespace ts {
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
@@ -1555,6 +1524,8 @@ namespace ts {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.MappedType:
|
||||
// All the children of these container types are never visible through another
|
||||
@@ -1650,7 +1621,7 @@ namespace ts {
|
||||
return state;
|
||||
}
|
||||
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration): void {
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration | JSDocSignature): void {
|
||||
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
//
|
||||
@@ -1752,21 +1723,34 @@ namespace ts {
|
||||
}
|
||||
|
||||
function delayedBindJSDocTypedefTag() {
|
||||
if (!delayedTypedefs) {
|
||||
if (!delayedTypeAliases) {
|
||||
return;
|
||||
}
|
||||
const saveContainer = container;
|
||||
const saveLastContainer = lastContainer;
|
||||
const saveBlockScopeContainer = blockScopeContainer;
|
||||
const saveParent = parent;
|
||||
for (const delay of delayedTypedefs) {
|
||||
({ container, lastContainer, blockScopeContainer, parent } = delay);
|
||||
bindBlockScopedDeclaration(delay.typedef, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
const saveCurrentFlow = currentFlow;
|
||||
for (const typeAlias of delayedTypeAliases) {
|
||||
const host = getJSDocHost(typeAlias);
|
||||
container = findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) || file;
|
||||
blockScopeContainer = getEnclosingBlockScopeContainer(host) || file;
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
parent = typeAlias;
|
||||
bind(typeAlias.typeExpression);
|
||||
if (!typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
|
||||
parent = typeAlias.parent;
|
||||
bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
}
|
||||
else {
|
||||
bind(typeAlias.fullName);
|
||||
}
|
||||
}
|
||||
container = saveContainer;
|
||||
lastContainer = saveLastContainer;
|
||||
blockScopeContainer = saveBlockScopeContainer;
|
||||
parent = saveParent;
|
||||
currentFlow = saveCurrentFlow;
|
||||
}
|
||||
|
||||
// The binder visits every node in the syntax tree so it is a convenient place to perform a single localized
|
||||
@@ -1946,7 +1930,6 @@ namespace ts {
|
||||
// Here the current node is "foo", which is a container, but the scope of "MyType" should
|
||||
// not be inside "foo". Therefore we always bind @typedef before bind the parent node,
|
||||
// and skip binding this tag later when binding all the other jsdoc tags.
|
||||
if (isInJavaScriptFile(node)) bindJSDocTypedefTagIfAny(node);
|
||||
|
||||
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
|
||||
// and then potentially add the symbol to an appropriate symbol table. Possible
|
||||
@@ -1978,26 +1961,21 @@ namespace ts {
|
||||
}
|
||||
else if (!skipTransformFlagAggregation && (node.transformFlags & TransformFlags.HasComputedFlags) === 0) {
|
||||
subtreeTransformFlags |= computeTransformFlagsForNode(node, 0);
|
||||
bindJSDoc(node);
|
||||
}
|
||||
inStrictMode = saveInStrictMode;
|
||||
}
|
||||
|
||||
function bindJSDocTypedefTagIfAny(node: Node) {
|
||||
if (!hasJSDocNodes(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const jsDoc of node.jsDoc) {
|
||||
if (!jsDoc.tags) {
|
||||
continue;
|
||||
function bindJSDoc(node: Node) {
|
||||
if (hasJSDocNodes(node)) {
|
||||
if (isInJavaScriptFile(node)) {
|
||||
for (const j of node.jsDoc) {
|
||||
bind(j);
|
||||
}
|
||||
}
|
||||
|
||||
for (const tag of jsDoc.tags) {
|
||||
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
const savedParent = parent;
|
||||
parent = jsDoc;
|
||||
bind(tag);
|
||||
parent = savedParent;
|
||||
else {
|
||||
for (const j of node.jsDoc) {
|
||||
setParentPointers(node, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2036,10 +2014,10 @@ namespace ts {
|
||||
// current "blockScopeContainer" needs to be set to its immediate namespace parent.
|
||||
if ((<Identifier>node).isInJSDocNamespace) {
|
||||
let parentNode = node.parent;
|
||||
while (parentNode && parentNode.kind !== SyntaxKind.JSDocTypedefTag) {
|
||||
while (parentNode && !isJSDocTypeAlias(parentNode)) {
|
||||
parentNode = parentNode.parent;
|
||||
}
|
||||
bindBlockScopedDeclaration(<Declaration>parentNode, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
bindBlockScopedDeclaration(parentNode as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
break;
|
||||
}
|
||||
// falls through
|
||||
@@ -2141,8 +2119,9 @@ namespace ts {
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration | JSDocSignature>node);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.MappedType:
|
||||
@@ -2205,6 +2184,9 @@ namespace ts {
|
||||
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);
|
||||
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
if (node.parent.kind === SyntaxKind.JSDocSignature) {
|
||||
return bindParameter(node as JSDocParameterTag);
|
||||
}
|
||||
if (node.parent.kind !== SyntaxKind.JSDocTypeLiteral) {
|
||||
break;
|
||||
}
|
||||
@@ -2215,13 +2197,9 @@ namespace ts {
|
||||
SymbolFlags.Property | SymbolFlags.Optional :
|
||||
SymbolFlags.Property;
|
||||
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag: {
|
||||
const { fullName } = node as JSDocTypedefTag;
|
||||
if (!fullName || fullName.kind === SyntaxKind.Identifier) {
|
||||
(delayedTypedefs || (delayedTypedefs = [])).push({ typedef: node as JSDocTypedefTag, container, lastContainer, blockScopeContainer, parent });
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2622,7 +2600,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindParameter(node: ParameterDeclaration) {
|
||||
function bindParameter(node: ParameterDeclaration | JSDocParameterTag) {
|
||||
if (node.kind === SyntaxKind.JSDocParameterTag && container.kind !== SyntaxKind.JSDocSignature) {
|
||||
return;
|
||||
}
|
||||
if (inStrictMode && !(node.flags & NodeFlags.Ambient)) {
|
||||
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
|
||||
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
|
||||
@@ -2630,7 +2611,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isBindingPattern(node.name)) {
|
||||
bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + node.parent.parameters.indexOf(node) as __String);
|
||||
bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + (node as ParameterDeclaration).parent.parameters.indexOf(node as ParameterDeclaration) as __String);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
|
||||
@@ -2690,18 +2671,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getInferTypeContainer(node: Node): ConditionalTypeNode {
|
||||
while (node) {
|
||||
const parent = node.parent;
|
||||
if (parent && parent.kind === SyntaxKind.ConditionalType && (<ConditionalTypeNode>parent).extendsType === node) {
|
||||
return <ConditionalTypeNode>parent;
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
return undefined;
|
||||
const extendsType = findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n);
|
||||
return extendsType && extendsType.parent as ConditionalTypeNode;
|
||||
}
|
||||
|
||||
function bindTypeParameter(node: TypeParameterDeclaration) {
|
||||
if (node.parent.kind === SyntaxKind.InferType) {
|
||||
if (isJSDocTemplateTag(node.parent)) {
|
||||
const container = find((node.parent.parent as JSDoc).tags, isJSDocTypeAlias) || getHostSignatureFromJSDoc(node.parent);
|
||||
if (container) {
|
||||
if (!container.locals) {
|
||||
container.locals = createSymbolTable();
|
||||
}
|
||||
declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
}
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.InferType) {
|
||||
const container = getInferTypeContainer(node.parent);
|
||||
if (container) {
|
||||
if (!container.locals) {
|
||||
@@ -3804,6 +3791,6 @@ namespace ts {
|
||||
*/
|
||||
function setParentPointers(parent: Node, child: Node): void {
|
||||
child.parent = parent;
|
||||
forEachChild(child, (childsChild) => setParentPointers(child, childsChild));
|
||||
forEachChild(child, grandchild => setParentPointers(child, grandchild));
|
||||
}
|
||||
}
|
||||
|
||||
+103
-69
@@ -1577,9 +1577,11 @@ namespace ts {
|
||||
|
||||
function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
|
||||
for (const decl of symbol.declarations) {
|
||||
const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent;
|
||||
if (decl.kind === SyntaxKind.TypeParameter && parent === container) {
|
||||
return true;
|
||||
if (decl.kind === SyntaxKind.TypeParameter) {
|
||||
const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent;
|
||||
if (parent === container) {
|
||||
return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2089,7 +2091,7 @@ namespace ts {
|
||||
let symbol: Symbol;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0;
|
||||
const symbolFromJSPrototype = isInJavaScriptFile(name) ? resolveEntityNameFromJSPrototype(name, meaning) : undefined;
|
||||
const symbolFromJSPrototype = isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined;
|
||||
symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true);
|
||||
if (!symbol) {
|
||||
return symbolFromJSPrototype;
|
||||
@@ -2144,25 +2146,34 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too.
|
||||
* 1. For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too.
|
||||
* Note that prototype-property assignment to locations outside the current file (eg globals) doesn't work, so
|
||||
* name resolution won't work either.
|
||||
* 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too.
|
||||
*/
|
||||
function resolveEntityNameFromJSPrototype(name: Identifier, meaning: SymbolFlags) {
|
||||
if (isJSDocTypeReference(name.parent) && isJSDocTag(name.parent.parent.parent)) {
|
||||
const host = getJSDocHost(name.parent.parent.parent as JSDocTag);
|
||||
if (isExpressionStatement(host) &&
|
||||
isBinaryExpression(host.expression) &&
|
||||
getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) {
|
||||
const symbol = getSymbolOfNode(host.expression.left);
|
||||
if (symbol) {
|
||||
const secondaryLocation = symbol.parent.valueDeclaration;
|
||||
return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true);
|
||||
}
|
||||
function resolveEntityNameFromJSSpecialAssignment(name: Identifier, meaning: SymbolFlags) {
|
||||
if (isJSDocTypeReference(name.parent)) {
|
||||
const host = getJSDocHost(name.parent);
|
||||
if (host) {
|
||||
const secondaryLocation = getJSSpecialAssignmentSymbol(getJSDocHost(name.parent.parent.parent as JSDocTag));
|
||||
return secondaryLocation && resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getJSSpecialAssignmentSymbol(host: HasJSDoc): Declaration | undefined {
|
||||
if (isPropertyAssignment(host) && isFunctionLike(host.initializer)) {
|
||||
const symbol = getSymbolOfNode(host.initializer);
|
||||
return symbol && symbol.valueDeclaration;
|
||||
}
|
||||
else if (isExpressionStatement(host) &&
|
||||
isBinaryExpression(host.expression) &&
|
||||
getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) {
|
||||
const symbol = getSymbolOfNode(host.expression.left);
|
||||
return symbol && symbol.parent.valueDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol {
|
||||
return resolveExternalModuleNameWorker(location, moduleReferenceExpression, Diagnostics.Cannot_find_module_0);
|
||||
}
|
||||
@@ -3606,8 +3617,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean): ParameterDeclaration {
|
||||
const parameterDeclaration = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
|
||||
Debug.assert(!!parameterDeclaration || isTransientSymbol(parameterSymbol));
|
||||
let parameterDeclaration: ParameterDeclaration | JSDocParameterTag = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
|
||||
if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) {
|
||||
parameterDeclaration = getDeclarationOfKind<JSDocParameterTag>(parameterSymbol, SyntaxKind.JSDocParameterTag);
|
||||
}
|
||||
|
||||
let parameterType = getTypeOfSymbol(parameterSymbol);
|
||||
if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) {
|
||||
@@ -3620,8 +3633,8 @@ namespace ts {
|
||||
const dotDotDotToken = isRest ? createToken(SyntaxKind.DotDotDotToken) : undefined;
|
||||
const name = parameterDeclaration
|
||||
? parameterDeclaration.name ?
|
||||
parameterDeclaration.name.kind === SyntaxKind.Identifier ?
|
||||
setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
|
||||
parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
|
||||
parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
|
||||
cloneBindingName(parameterDeclaration.name) :
|
||||
symbolName(parameterSymbol)
|
||||
: symbolName(parameterSymbol);
|
||||
@@ -4026,8 +4039,9 @@ namespace ts {
|
||||
|
||||
function determineIfDeclarationIsVisible() {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
// Top-level jsdoc typedefs are considered exported
|
||||
// Top-level jsdoc type aliases are considered exported
|
||||
// First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file
|
||||
return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent));
|
||||
case SyntaxKind.BindingElement:
|
||||
@@ -4802,7 +4816,7 @@ namespace ts {
|
||||
if (symbol.flags & SymbolFlags.Prototype) {
|
||||
return links.type = getTypeOfPrototypeProperty(symbol);
|
||||
}
|
||||
// CommonsJS require/module/exports all have type any.
|
||||
// CommonsJS require and module both have type any.
|
||||
if (symbol === requireSymbol || symbol === moduleSymbol) {
|
||||
return links.type = anyType;
|
||||
}
|
||||
@@ -4837,7 +4851,7 @@ namespace ts {
|
||||
declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
type = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol);
|
||||
}
|
||||
else if (isJSDocPropertyTag(declaration)
|
||||
else if (isJSDocPropertyLikeTag(declaration)
|
||||
|| isPropertyAccessExpression(declaration)
|
||||
|| isIdentifier(declaration)
|
||||
|| (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration))
|
||||
@@ -5139,6 +5153,8 @@ namespace ts {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.MappedType:
|
||||
case SyntaxKind.ConditionalType:
|
||||
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
|
||||
@@ -5168,9 +5184,11 @@ namespace ts {
|
||||
function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] {
|
||||
let result: TypeParameter[];
|
||||
for (const node of symbol.declarations) {
|
||||
if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration ||
|
||||
node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration || node.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag>node;
|
||||
if (node.kind === SyntaxKind.InterfaceDeclaration ||
|
||||
node.kind === SyntaxKind.ClassDeclaration ||
|
||||
node.kind === SyntaxKind.ClassExpression ||
|
||||
isTypeAlias(node)) {
|
||||
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag>node;
|
||||
const typeParameters = getEffectiveTypeParameterDeclarations(declaration);
|
||||
if (typeParameters) {
|
||||
result = appendTypeParameters(result, typeParameters);
|
||||
@@ -5466,9 +5484,9 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
const declaration = <JSDocTypedefTag | TypeAliasDeclaration>find(symbol.declarations, d =>
|
||||
d.kind === SyntaxKind.JSDocTypedefTag || d.kind === SyntaxKind.TypeAliasDeclaration);
|
||||
const typeNode = declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type;
|
||||
const declaration = <JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration>find(symbol.declarations, d =>
|
||||
isJSDocTypeAlias(d) || d.kind === SyntaxKind.TypeAliasDeclaration);
|
||||
const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type;
|
||||
// If typeNode is missing, we will error in checkJSDocTypedefTag.
|
||||
let type = typeNode ? getTypeFromTypeNode(typeNode) : unknownType;
|
||||
|
||||
@@ -6036,7 +6054,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSignature(
|
||||
declaration: SignatureDeclaration,
|
||||
declaration: SignatureDeclaration | JSDocSignature,
|
||||
typeParameters: TypeParameter[],
|
||||
thisParameter: Symbol | undefined,
|
||||
parameters: Symbol[],
|
||||
@@ -7046,8 +7064,8 @@ namespace ts {
|
||||
return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol;
|
||||
}
|
||||
|
||||
function isOptionalParameter(node: ParameterDeclaration) {
|
||||
if (hasQuestionToken(node) || isJSDocOptionalParameter(node)) {
|
||||
function isOptionalParameter(node: ParameterDeclaration | JSDocParameterTag) {
|
||||
if (hasQuestionToken(node) || isOptionalJSDocParameterTag(node) || isJSDocOptionalParameter(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7067,6 +7085,14 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isOptionalJSDocParameterTag(node: Node): node is JSDocParameterTag {
|
||||
if (!isJSDocParameterTag(node)) {
|
||||
return false;
|
||||
}
|
||||
const { isBracketed, typeExpression } = node;
|
||||
return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
|
||||
}
|
||||
|
||||
function createTypePredicateFromTypePredicateNode(node: TypePredicateNode): IdentifierTypePredicate | ThisTypePredicate {
|
||||
const { parameterName } = node;
|
||||
const type = getTypeFromTypeNode(node.type);
|
||||
@@ -7142,7 +7168,7 @@ namespace ts {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature {
|
||||
function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature {
|
||||
const links = getNodeLinks(declaration);
|
||||
if (!links.resolvedSignature) {
|
||||
const parameters: Symbol[] = [];
|
||||
@@ -7165,6 +7191,7 @@ namespace ts {
|
||||
const param = declaration.parameters[i];
|
||||
|
||||
let paramSymbol = param.symbol;
|
||||
const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type;
|
||||
// Include parameter symbol instead of property symbol in the signature
|
||||
if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) {
|
||||
const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, undefined, undefined, /*isUse*/ false);
|
||||
@@ -7178,13 +7205,14 @@ namespace ts {
|
||||
parameters.push(paramSymbol);
|
||||
}
|
||||
|
||||
if (param.type && param.type.kind === SyntaxKind.LiteralType) {
|
||||
if (type && type.kind === SyntaxKind.LiteralType) {
|
||||
hasLiteralTypes = true;
|
||||
}
|
||||
|
||||
// Record a new minimum argument count if this is not an optional parameter
|
||||
const isOptionalParameter = param.initializer || param.questionToken || param.dotDotDotToken ||
|
||||
iife && parameters.length > iife.arguments.length && !param.type ||
|
||||
const isOptionalParameter = isOptionalJSDocParameterTag(param) ||
|
||||
param.initializer || param.questionToken || param.dotDotDotToken ||
|
||||
iife && parameters.length > iife.arguments.length && !type ||
|
||||
isUntypedSignatureInJSFile ||
|
||||
isJSDocOptionalParameter(param);
|
||||
if (!isOptionalParameter) {
|
||||
@@ -7220,8 +7248,8 @@ namespace ts {
|
||||
* OR
|
||||
* 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...`
|
||||
*/
|
||||
function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration, parameters: Symbol[]): boolean {
|
||||
if (!containsArgumentsReference(declaration)) {
|
||||
function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration | JSDocSignature, parameters: Symbol[]): boolean {
|
||||
if (isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) {
|
||||
return false;
|
||||
}
|
||||
const lastParam = lastOrUndefined(declaration.parameters);
|
||||
@@ -7240,9 +7268,9 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, isJSConstructSignature: boolean, classType: Type) {
|
||||
function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration | JSDocSignature, isJSConstructSignature: boolean, classType: Type) {
|
||||
if (isJSConstructSignature) {
|
||||
return getTypeFromTypeNode(declaration.parameters[0].type);
|
||||
return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type);
|
||||
}
|
||||
else if (classType) {
|
||||
return classType;
|
||||
@@ -7656,11 +7684,11 @@ namespace ts {
|
||||
const missingAugmentsTag = isJs && node.parent.kind !== SyntaxKind.JSDocAugmentsTag;
|
||||
const diag = minTypeArgumentCount === typeParameters.length
|
||||
? missingAugmentsTag
|
||||
? Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag
|
||||
: Diagnostics.Generic_type_0_requires_1_type_argument_s
|
||||
: missingAugmentsTag
|
||||
? Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag
|
||||
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments;
|
||||
? Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag
|
||||
: Diagnostics.Generic_type_0_requires_1_type_argument_s
|
||||
: missingAugmentsTag
|
||||
? Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag
|
||||
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments;
|
||||
const typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType);
|
||||
error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length);
|
||||
if (!isJs) {
|
||||
@@ -7675,7 +7703,7 @@ namespace ts {
|
||||
return createTypeReference(<GenericType>type, typeArguments);
|
||||
}
|
||||
return checkNoTypeArguments(node, symbol) ? type : unknownType;
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[]): Type {
|
||||
const type = getDeclaredTypeOfSymbol(symbol);
|
||||
@@ -7702,18 +7730,18 @@ namespace ts {
|
||||
const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
|
||||
if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) {
|
||||
error(node,
|
||||
minTypeArgumentCount === typeParameters.length
|
||||
? Diagnostics.Generic_type_0_requires_1_type_argument_s
|
||||
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments,
|
||||
symbolToString(symbol),
|
||||
minTypeArgumentCount,
|
||||
typeParameters.length);
|
||||
minTypeArgumentCount === typeParameters.length
|
||||
? Diagnostics.Generic_type_0_requires_1_type_argument_s
|
||||
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments,
|
||||
symbolToString(symbol),
|
||||
minTypeArgumentCount,
|
||||
typeParameters.length);
|
||||
return unknownType;
|
||||
}
|
||||
return getTypeAliasInstantiation(symbol, typeArguments);
|
||||
}
|
||||
return checkNoTypeArguments(node, symbol) ? type : unknownType;
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined {
|
||||
switch (node.kind) {
|
||||
@@ -7828,7 +7856,7 @@ namespace ts {
|
||||
|
||||
function getConstrainedTypeVariable(typeVariable: TypeVariable, node: Node) {
|
||||
let constraints: Type[];
|
||||
while (node && !isStatement(node)) {
|
||||
while (node && !isStatement(node) && node.kind !== SyntaxKind.JSDocComment) {
|
||||
const parent = node.parent;
|
||||
if (parent.kind === SyntaxKind.ConditionalType && node === (<ConditionalTypeNode>parent).trueType) {
|
||||
const constraint = getImpliedConstraint(typeVariable, (<ConditionalTypeNode>parent).checkType, (<ConditionalTypeNode>parent).extendsType);
|
||||
@@ -8396,8 +8424,9 @@ namespace ts {
|
||||
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), UnionReduction.Literal,
|
||||
getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
|
||||
aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -8506,8 +8535,9 @@ namespace ts {
|
||||
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode),
|
||||
getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
|
||||
aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -8816,7 +8846,7 @@ namespace ts {
|
||||
const type = <MappedType>createObjectType(ObjectFlags.Mapped, node.symbol);
|
||||
type.declaration = node;
|
||||
type.aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
type.aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
|
||||
type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(type.aliasSymbol);
|
||||
links.resolvedType = type;
|
||||
// Eagerly resolve the constraint type which forces an error if the constraint type circularly
|
||||
// references itself through one or more type aliases.
|
||||
@@ -8924,7 +8954,8 @@ namespace ts {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const checkType = getTypeFromTypeNode(node.checkType);
|
||||
const aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
|
||||
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
|
||||
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isPossiblyReferencedInConditionalType(tp, node));
|
||||
const root: ConditionalRoot = {
|
||||
@@ -8937,7 +8968,7 @@ namespace ts {
|
||||
inferTypeParameters: getInferTypeParameters(node),
|
||||
outerTypeParameters,
|
||||
instantiations: undefined,
|
||||
aliasSymbol: getAliasSymbolForTypeNode(node),
|
||||
aliasSymbol,
|
||||
aliasTypeArguments
|
||||
};
|
||||
links.resolvedType = getConditionalType(root, /*mapper*/ undefined);
|
||||
@@ -9041,7 +9072,7 @@ namespace ts {
|
||||
else {
|
||||
let type = createObjectType(ObjectFlags.Anonymous, node.symbol);
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
|
||||
type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
|
||||
if (isJSDocTypeLiteral(node) && node.isArrayType) {
|
||||
type = createArrayType(type);
|
||||
}
|
||||
@@ -9052,11 +9083,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getAliasSymbolForTypeNode(node: TypeNode) {
|
||||
return (node.parent.kind === SyntaxKind.TypeAliasDeclaration || node.parent.kind === SyntaxKind.JSDocTypedefTag) ? getSymbolOfNode(node.parent) : undefined;
|
||||
return isTypeAlias(node.parent) ? getSymbolOfNode(node.parent) : undefined;
|
||||
}
|
||||
|
||||
function getAliasTypeArgumentsForTypeNode(node: TypeNode) {
|
||||
const symbol = getAliasSymbolForTypeNode(node);
|
||||
function getTypeArgumentsForAliasSymbol(symbol: Symbol) {
|
||||
return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined;
|
||||
}
|
||||
|
||||
@@ -9314,6 +9344,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
|
||||
case SyntaxKind.TypeOperator:
|
||||
return getTypeFromTypeOperatorNode(<TypeOperatorNode>node);
|
||||
@@ -9991,8 +10022,8 @@ namespace ts {
|
||||
function compareTypePredicateRelatedTo(
|
||||
source: TypePredicate,
|
||||
target: TypePredicate,
|
||||
sourceDeclaration: SignatureDeclaration,
|
||||
targetDeclaration: SignatureDeclaration,
|
||||
sourceDeclaration: SignatureDeclaration | JSDocSignature,
|
||||
targetDeclaration: SignatureDeclaration | JSDocSignature,
|
||||
reportErrors: boolean,
|
||||
errorReporter: ErrorReporter,
|
||||
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
|
||||
@@ -21761,8 +21792,9 @@ namespace ts {
|
||||
switch (d.kind) {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
// A jsdoc typedef is, by definition, a type alias
|
||||
// A jsdoc typedef and callback are, by definition, type aliases
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return DeclarationSpaces.ExportType;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return isAmbientModule(d as ModuleDeclaration) || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated
|
||||
@@ -22297,7 +22329,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkJSDocTypedefTag(node: JSDocTypedefTag) {
|
||||
function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag) {
|
||||
if (!node.typeExpression) {
|
||||
// If the node had `@property` tags, `typeExpression` would have been set to the first property tag.
|
||||
error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags);
|
||||
@@ -25212,7 +25244,8 @@ namespace ts {
|
||||
case SyntaxKind.JSDocAugmentsTag:
|
||||
return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return checkJSDocTypedefTag(node as JSDocTypedefTag);
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return checkJSDocTypeAliasTag(node as JSDocTypedefTag);
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
return checkJSDocParameterTag(node as JSDocParameterTag);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
@@ -26423,9 +26456,10 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRequiredInitializedParameter(parameter: ParameterDeclaration) {
|
||||
function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag) {
|
||||
return strictNullChecks &&
|
||||
!isOptionalParameter(parameter) &&
|
||||
!isJSDocParameterTag(parameter) &&
|
||||
parameter.initializer &&
|
||||
!hasModifier(parameter, ModifierFlags.ParameterPropertyModifier);
|
||||
}
|
||||
|
||||
+94
-39
@@ -489,6 +489,15 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
|
||||
}
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
|
||||
visitNode(cbNode, (node as JSDocCallbackTag).typeExpression);
|
||||
case SyntaxKind.JSDocSignature:
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).parameters) ||
|
||||
visitNode(cbNode, (<SignatureDeclaration>node).type);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
|
||||
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
|
||||
@@ -6331,8 +6340,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
const enum PropertyLikeParse {
|
||||
Property,
|
||||
Parameter,
|
||||
Property = 1 << 0,
|
||||
Parameter = 1 << 1,
|
||||
CallbackParameter = 1 << 2,
|
||||
}
|
||||
|
||||
export function parseJSDocCommentWorker(start: number, length: number): JSDoc {
|
||||
@@ -6386,7 +6396,7 @@ namespace ts {
|
||||
case SyntaxKind.AtToken:
|
||||
if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
|
||||
removeTrailingNewlines(comments);
|
||||
parseTag(indent);
|
||||
addTag(parseTag(indent));
|
||||
// NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag.
|
||||
// Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning
|
||||
// for malformed examples like `/** @param {string} x @returns {number} the length */`
|
||||
@@ -6503,8 +6513,7 @@ namespace ts {
|
||||
case "arg":
|
||||
case "argument":
|
||||
case "param":
|
||||
addTag(parseParameterOrPropertyTag(atToken, tagName, PropertyLikeParse.Parameter, indent));
|
||||
return;
|
||||
return parseParameterOrPropertyTag(atToken, tagName, PropertyLikeParse.Parameter, indent);
|
||||
case "return":
|
||||
case "returns":
|
||||
tag = parseReturnTag(atToken, tagName);
|
||||
@@ -6516,7 +6525,10 @@ namespace ts {
|
||||
tag = parseTypeTag(atToken, tagName);
|
||||
break;
|
||||
case "typedef":
|
||||
tag = parseTypedefTag(atToken, tagName);
|
||||
tag = parseTypedefTag(atToken, tagName, indent);
|
||||
break;
|
||||
case "callback":
|
||||
tag = parseCallbackTag(atToken, tagName, indent);
|
||||
break;
|
||||
default:
|
||||
tag = parseUnknownTag(atToken, tagName);
|
||||
@@ -6531,8 +6543,11 @@ namespace ts {
|
||||
// a badly malformed tag should not be added to the list of tags
|
||||
return;
|
||||
}
|
||||
tag.comment = parseTagComments(indent + tag.end - tag.pos);
|
||||
addTag(tag);
|
||||
if (!tag.comment) {
|
||||
// some tags, like typedef and callback, have already parsed their comments earlier
|
||||
tag.comment = parseTagComments(indent + tag.end - tag.pos);
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
function parseTagComments(indent: number): string | undefined {
|
||||
@@ -6605,6 +6620,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addTag(tag: JSDocTag): void {
|
||||
if (!tag) {
|
||||
return;
|
||||
}
|
||||
if (!tags) {
|
||||
tags = [tag];
|
||||
tagsPos = tag.pos;
|
||||
@@ -6665,9 +6683,9 @@ namespace ts {
|
||||
typeExpression = tryParseTypeExpression();
|
||||
}
|
||||
|
||||
const result = target === PropertyLikeParse.Parameter ?
|
||||
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos) :
|
||||
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
|
||||
const result = target === PropertyLikeParse.Property ?
|
||||
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos) :
|
||||
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos);
|
||||
let comment: string | undefined;
|
||||
if (indent !== undefined) comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos);
|
||||
const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, name, target);
|
||||
@@ -6771,27 +6789,17 @@ namespace ts {
|
||||
return finishNode(tag);
|
||||
}
|
||||
|
||||
function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
|
||||
function parseTypedefTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
|
||||
typedefTag.atToken = atToken;
|
||||
typedefTag.tagName = tagName;
|
||||
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
|
||||
if (typedefTag.fullName) {
|
||||
let rightNode = typedefTag.fullName;
|
||||
while (true) {
|
||||
if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
|
||||
// if node is identifier - use it as name
|
||||
// otherwise use name of the rightmost part that we were able to parse
|
||||
typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
|
||||
break;
|
||||
}
|
||||
rightNode = rightNode.body;
|
||||
}
|
||||
}
|
||||
typedefTag.fullName = parseJSDocTypeNameWithNamespace();
|
||||
typedefTag.name = getJSDocTypeAliasName(typedefTag.fullName);
|
||||
skipWhitespace();
|
||||
typedefTag.comment = parseTagComments(indent);
|
||||
|
||||
typedefTag.typeExpression = typeExpression;
|
||||
if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
|
||||
@@ -6826,23 +6834,69 @@ namespace ts {
|
||||
}
|
||||
|
||||
return finishNode(typedefTag);
|
||||
}
|
||||
|
||||
function parseJSDocTypeNameWithNamespace(flags: NodeFlags) {
|
||||
const pos = scanner.getTokenPos();
|
||||
const typeNameOrNamespaceName = parseJSDocIdentifierName();
|
||||
function parseJSDocTypeNameWithNamespace(nested?: boolean) {
|
||||
const pos = scanner.getTokenPos();
|
||||
const typeNameOrNamespaceName = parseJSDocIdentifierName();
|
||||
|
||||
if (typeNameOrNamespaceName && parseOptional(SyntaxKind.DotToken)) {
|
||||
const jsDocNamespaceNode = <JSDocNamespaceDeclaration>createNode(SyntaxKind.ModuleDeclaration, pos);
|
||||
jsDocNamespaceNode.flags |= flags;
|
||||
jsDocNamespaceNode.name = typeNameOrNamespaceName;
|
||||
jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace);
|
||||
return finishNode(jsDocNamespaceNode);
|
||||
if (typeNameOrNamespaceName && parseOptional(SyntaxKind.DotToken)) {
|
||||
const jsDocNamespaceNode = <JSDocNamespaceDeclaration>createNode(SyntaxKind.ModuleDeclaration, pos);
|
||||
if (nested) {
|
||||
jsDocNamespaceNode.flags |= NodeFlags.NestedNamespace;
|
||||
}
|
||||
jsDocNamespaceNode.name = typeNameOrNamespaceName;
|
||||
jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(/*nested*/ true);
|
||||
return finishNode(jsDocNamespaceNode);
|
||||
}
|
||||
|
||||
if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) {
|
||||
typeNameOrNamespaceName.isInJSDocNamespace = true;
|
||||
if (typeNameOrNamespaceName && nested) {
|
||||
typeNameOrNamespaceName.isInJSDocNamespace = true;
|
||||
}
|
||||
return typeNameOrNamespaceName;
|
||||
}
|
||||
|
||||
function parseCallbackTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocCallbackTag {
|
||||
const callbackTag = createNode(SyntaxKind.JSDocCallbackTag, atToken.pos) as JSDocCallbackTag;
|
||||
callbackTag.atToken = atToken;
|
||||
callbackTag.tagName = tagName;
|
||||
callbackTag.fullName = parseJSDocTypeNameWithNamespace();
|
||||
callbackTag.name = getJSDocTypeAliasName(callbackTag.fullName);
|
||||
skipWhitespace();
|
||||
callbackTag.comment = parseTagComments(indent);
|
||||
|
||||
let child: JSDocParameterTag | false;
|
||||
const start = scanner.getStartPos();
|
||||
const jsdocSignature = createNode(SyntaxKind.JSDocSignature, start) as JSDocSignature;
|
||||
jsdocSignature.parameters = [];
|
||||
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter) as JSDocParameterTag)) {
|
||||
jsdocSignature.parameters = append(jsdocSignature.parameters as MutableNodeArray<JSDocParameterTag>, child);
|
||||
}
|
||||
const returnTag = tryParse(() => {
|
||||
if (token() === SyntaxKind.AtToken) {
|
||||
nextJSDocToken();
|
||||
const tag = parseTag(indent);
|
||||
if (tag && tag.kind === SyntaxKind.JSDocReturnTag) {
|
||||
return tag as JSDocReturnTag;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (returnTag) {
|
||||
jsdocSignature.type = returnTag;
|
||||
}
|
||||
callbackTag.typeExpression = finishNode(jsdocSignature);
|
||||
return finishNode(callbackTag);
|
||||
}
|
||||
|
||||
function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) {
|
||||
if (fullName) {
|
||||
let rightNode = fullName;
|
||||
while (true) {
|
||||
if (ts.isIdentifier(rightNode) || !rightNode.body) {
|
||||
return ts.isIdentifier(rightNode) ? rightNode : rightNode.name;
|
||||
}
|
||||
rightNode = rightNode.body;
|
||||
}
|
||||
return typeNameOrNamespaceName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6872,6 +6926,7 @@ namespace ts {
|
||||
if (canParseTag) {
|
||||
const child = tryParseChildTag(target);
|
||||
if (child && child.kind === SyntaxKind.JSDocParameterTag &&
|
||||
target !== PropertyLikeParse.CallbackParameter &&
|
||||
(ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) {
|
||||
return false;
|
||||
}
|
||||
@@ -6920,12 +6975,12 @@ namespace ts {
|
||||
case "arg":
|
||||
case "argument":
|
||||
case "param":
|
||||
t = PropertyLikeParse.Parameter;
|
||||
t = PropertyLikeParse.Parameter | PropertyLikeParse.CallbackParameter;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (target !== t) {
|
||||
if (!(target & t)) {
|
||||
return false;
|
||||
}
|
||||
const tag = parseParameterOrPropertyTag(atToken, tagName, target, /*indent*/ undefined);
|
||||
|
||||
+19
-2
@@ -413,9 +413,11 @@ namespace ts {
|
||||
JSDocVariadicType,
|
||||
JSDocComment,
|
||||
JSDocTypeLiteral,
|
||||
JSDocSignature,
|
||||
JSDocTag,
|
||||
JSDocAugmentsTag,
|
||||
JSDocClassTag,
|
||||
JSDocCallbackTag,
|
||||
JSDocParameterTag,
|
||||
JSDocReturnTag,
|
||||
JSDocTypeTag,
|
||||
@@ -2053,7 +2055,7 @@ namespace ts {
|
||||
|
||||
export type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
|
||||
|
||||
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
|
||||
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
|
||||
|
||||
export interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
|
||||
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
|
||||
@@ -2387,6 +2389,21 @@ namespace ts {
|
||||
typeExpression?: JSDocTypeExpression | JSDocTypeLiteral;
|
||||
}
|
||||
|
||||
export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocCallbackTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
typeExpression: JSDocSignature;
|
||||
}
|
||||
|
||||
export interface JSDocSignature extends JSDocType, Declaration {
|
||||
kind: SyntaxKind.JSDocSignature;
|
||||
typeParameters?: ReadonlyArray<JSDocTemplateTag>;
|
||||
parameters: ReadonlyArray<JSDocParameterTag>;
|
||||
type: JSDocReturnTag | undefined;
|
||||
}
|
||||
|
||||
export interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
name: EntityName;
|
||||
@@ -4032,7 +4049,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface Signature {
|
||||
declaration?: SignatureDeclaration; // Originating declaration
|
||||
declaration?: SignatureDeclaration | JSDocSignature; // Originating declaration
|
||||
typeParameters?: TypeParameter[]; // Type parameters (undefined if non-generic)
|
||||
parameters: Symbol[]; // Parameters
|
||||
/* @internal */
|
||||
|
||||
+67
-35
@@ -520,6 +520,9 @@ namespace ts {
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
return true;
|
||||
default:
|
||||
assertTypeIsNever(node);
|
||||
@@ -561,14 +564,7 @@ namespace ts {
|
||||
// Gets the nearest enclosing block scope container that has the provided node
|
||||
// as a descendant, that is not the provided node.
|
||||
export function getEnclosingBlockScopeContainer(node: Node): Node {
|
||||
let current = node.parent;
|
||||
while (current) {
|
||||
if (isBlockScope(current, current.parent)) {
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
return findAncestor(node.parent, current => isBlockScope(current, current.parent));
|
||||
}
|
||||
|
||||
// Return display name of an identifier
|
||||
@@ -1803,6 +1799,14 @@ namespace ts {
|
||||
((node as JSDocFunctionType).parameters[0].name as Identifier).escapedText === "new";
|
||||
}
|
||||
|
||||
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag;
|
||||
}
|
||||
|
||||
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration {
|
||||
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
|
||||
}
|
||||
|
||||
function getSourceOfAssignment(node: Node): Node {
|
||||
return isExpressionStatement(node) &&
|
||||
node.expression && isBinaryExpression(node.expression) &&
|
||||
@@ -1826,6 +1830,8 @@ namespace ts {
|
||||
return v && v.initializer;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return (node as PropertyDeclaration).initializer;
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
return (node as PropertyAssignment).initializer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1907,7 +1913,7 @@ namespace ts {
|
||||
return parameter && parameter.symbol;
|
||||
}
|
||||
|
||||
export function getHostSignatureFromJSDoc(node: JSDocParameterTag): SignatureDeclaration | undefined {
|
||||
export function getHostSignatureFromJSDoc(node: JSDocTag): SignatureDeclaration | undefined {
|
||||
const host = getJSDocHost(node);
|
||||
const decl = getSourceOfDefaultedAssignment(host) ||
|
||||
getSourceOfAssignment(host) ||
|
||||
@@ -1918,18 +1924,12 @@ namespace ts {
|
||||
return decl && isFunctionLike(decl) ? decl : undefined;
|
||||
}
|
||||
|
||||
export function getJSDocHost(node: JSDocTag): HasJSDoc {
|
||||
while (node.parent.kind === SyntaxKind.JSDocTypeLiteral) {
|
||||
if (node.parent.parent.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
node = node.parent.parent as JSDocTypedefTag;
|
||||
}
|
||||
else {
|
||||
// node.parent.parent is a type expression, child of a parameter type
|
||||
node = node.parent.parent.parent as JSDocParameterTag;
|
||||
}
|
||||
export function getJSDocHost(node: Node): HasJSDoc {
|
||||
const comment = findAncestor(node.parent,
|
||||
node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : node.kind === SyntaxKind.JSDocComment);
|
||||
if (comment) {
|
||||
return (comment as JSDoc).parent;
|
||||
}
|
||||
Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment);
|
||||
return node.parent!.parent!;
|
||||
}
|
||||
|
||||
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {
|
||||
@@ -1938,13 +1938,14 @@ namespace ts {
|
||||
return find(typeParameters, p => p.name.escapedText === name);
|
||||
}
|
||||
|
||||
export function hasRestParameter(s: SignatureDeclaration): boolean {
|
||||
const last = lastOrUndefined(s.parameters);
|
||||
export function hasRestParameter(s: SignatureDeclaration | JSDocSignature): boolean {
|
||||
const last = lastOrUndefined<ParameterDeclaration | JSDocParameterTag>(s.parameters);
|
||||
return last && isRestParameter(last);
|
||||
}
|
||||
|
||||
export function isRestParameter(node: ParameterDeclaration): boolean {
|
||||
return node.dotDotDotToken !== undefined || node.type && node.type.kind === SyntaxKind.JSDocVariadicType;
|
||||
export function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): boolean {
|
||||
const type = isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type;
|
||||
return (node as ParameterDeclaration).dotDotDotToken !== undefined || type && type.kind === SyntaxKind.JSDocVariadicType;
|
||||
}
|
||||
|
||||
export const enum AssignmentKind {
|
||||
@@ -2998,8 +2999,9 @@ namespace ts {
|
||||
return parameter && parameter.type;
|
||||
}
|
||||
|
||||
export function getThisParameter(signature: SignatureDeclaration): ParameterDeclaration | undefined {
|
||||
if (signature.parameters.length) {
|
||||
export function getThisParameter(signature: SignatureDeclaration | JSDocSignature): ParameterDeclaration | undefined {
|
||||
// callback tags do not currently support this parameters
|
||||
if (signature.parameters.length && !isJSDocSignature(signature)) {
|
||||
const thisParameter = signature.parameters[0];
|
||||
if (parameterIsThisKeyword(thisParameter)) {
|
||||
return thisParameter;
|
||||
@@ -3085,7 +3087,10 @@ namespace ts {
|
||||
* Gets the effective return type annotation of a signature. If the node was parsed in a
|
||||
* JavaScript file, gets the return type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode | undefined {
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration | JSDocSignature): TypeNode | undefined {
|
||||
if (isJSDocSignature(node)) {
|
||||
return node.type && node.type.typeExpression && node.type.typeExpression.type;
|
||||
}
|
||||
return node.type || (isInJavaScriptFile(node) ? getJSDocReturnType(node) : undefined);
|
||||
}
|
||||
|
||||
@@ -3093,15 +3098,30 @@ namespace ts {
|
||||
* Gets the effective type parameters. If the node was parsed in a
|
||||
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters | JSDocTypedefTag) {
|
||||
return isJSDocTypedefTag(node)
|
||||
? getJSDocTypeParameterDeclarations(node)
|
||||
: node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined);
|
||||
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters) {
|
||||
if (isJSDocSignature(node)) {
|
||||
return undefined;
|
||||
}
|
||||
if (isJSDocTypeAlias(node)) {
|
||||
Debug.assert(node.parent.kind === SyntaxKind.JSDocComment);
|
||||
const templateTags = flatMap(filter(node.parent.tags, isJSDocTemplateTag), tag => tag.typeParameters) as ReadonlyArray<TypeParameterDeclaration>;
|
||||
const templateTagNodes = templateTags as NodeArray<TypeParameterDeclaration>;
|
||||
templateTagNodes.pos = templateTagNodes.length > 0 ? first(templateTagNodes).pos : node.pos;
|
||||
templateTagNodes.end = templateTagNodes.length > 0 ? last(templateTagNodes).end : node.end;
|
||||
templateTagNodes.hasTrailingComma = false;
|
||||
return templateTagNodes;
|
||||
}
|
||||
return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined);
|
||||
}
|
||||
|
||||
export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters | JSDocTypedefTag) {
|
||||
const templateTag = getJSDocTemplateTag(node);
|
||||
return templateTag && templateTag.typeParameters;
|
||||
export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters) {
|
||||
const tags = filter(getJSDocTags(node), isJSDocTemplateTag);
|
||||
for (const tag of tags) {
|
||||
if (!(tag.parent.kind === SyntaxKind.JSDocComment && find(tag.parent.tags, isJSDocTypeAlias))) {
|
||||
// template tags are only available when a typedef isn't already using them
|
||||
return tag.typeParameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4638,6 +4658,8 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return (declaration as JSDocCallbackTag).name;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
|
||||
case SyntaxKind.ExportAssignment: {
|
||||
@@ -5475,6 +5497,14 @@ namespace ts {
|
||||
export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral {
|
||||
return node.kind === SyntaxKind.JSDocTypeLiteral;
|
||||
}
|
||||
|
||||
export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag {
|
||||
return node.kind === SyntaxKind.JSDocCallbackTag;
|
||||
}
|
||||
|
||||
export function isJSDocSignature(node: Node): node is JSDocSignature {
|
||||
return node.kind === SyntaxKind.JSDocSignature;
|
||||
}
|
||||
}
|
||||
|
||||
// Node tests
|
||||
@@ -5636,6 +5666,7 @@ namespace ts {
|
||||
switch (kind) {
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.JSDocSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.FunctionType:
|
||||
@@ -6104,6 +6135,7 @@ namespace ts {
|
||||
|| kind === SyntaxKind.TypeParameter
|
||||
|| kind === SyntaxKind.VariableDeclaration
|
||||
|| kind === SyntaxKind.JSDocTypedefTag
|
||||
|| kind === SyntaxKind.JSDocCallbackTag
|
||||
|| kind === SyntaxKind.JSDocPropertyTag;
|
||||
}
|
||||
|
||||
@@ -6254,7 +6286,7 @@ namespace ts {
|
||||
|
||||
/** True if node is of a kind that may contain comment text. */
|
||||
export function isJSDocCommentContainingNode(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.JSDocComment || isJSDocTag(node) || isJSDocTypeLiteral(node);
|
||||
return node.kind === SyntaxKind.JSDocComment || isJSDocTag(node) || isJSDocTypeLiteral(node) || isJSDocSignature(node);
|
||||
}
|
||||
|
||||
// TODO: determine what this does before making it public.
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getToken(sourceFile: SourceFile, pos: number): Node {
|
||||
const token = findPrecedingToken(pos, sourceFile);
|
||||
const token = findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true);
|
||||
// this handles var ["computed"] = 12;
|
||||
return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile) : token;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ namespace ts.codefix {
|
||||
break;
|
||||
|
||||
case SyntaxKind.TypeParameter:
|
||||
const typeParameters = (<DeclarationWithTypeParameters>parent.parent).typeParameters;
|
||||
const typeParameters = getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>parent.parent);
|
||||
if (typeParameters.length === 1) {
|
||||
const previousToken = getTokenAtPosition(sourceFile, typeParameters.pos - 1, /*includeJsDocComment*/ false);
|
||||
const nextToken = getTokenAtPosition(sourceFile, typeParameters.end, /*includeJsDocComment*/ false);
|
||||
@@ -315,4 +315,4 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace ts.JsDoc {
|
||||
"author",
|
||||
"argument",
|
||||
"borrows",
|
||||
"callback",
|
||||
"class",
|
||||
"constant",
|
||||
"constructor",
|
||||
@@ -68,10 +69,12 @@ namespace ts.JsDoc {
|
||||
|
||||
function getCommentHavingNodes(declaration: Declaration): ReadonlyArray<JSDoc | JSDocTag> {
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return [declaration as JSDocPropertyTag];
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return [(declaration as JSDocTypedefTag).parent];
|
||||
return [(declaration as JSDocTypedefTag), (declaration as JSDocTypedefTag).parent];
|
||||
default:
|
||||
return getJSDocCommentsAndTags(declaration);
|
||||
}
|
||||
@@ -98,6 +101,7 @@ namespace ts.JsDoc {
|
||||
case SyntaxKind.JSDocTypeTag:
|
||||
return withNode((tag as JSDocTypeTag).typeExpression);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
const { name } = tag as JSDocTypedefTag | JSDocPropertyTag | JSDocParameterTag;
|
||||
|
||||
@@ -290,7 +290,7 @@ namespace ts.NavigationBar {
|
||||
if (hasJSDocNodes(node)) {
|
||||
forEach(node.jsDoc, jsDoc => {
|
||||
forEach(jsDoc.tags, tag => {
|
||||
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
if (isJSDocTypeAlias(tag)) {
|
||||
addLeafNode(tag);
|
||||
}
|
||||
});
|
||||
@@ -414,8 +414,6 @@ namespace ts.NavigationBar {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.ClassExpression:
|
||||
return getFunctionOrClassName(<FunctionExpression | ArrowFunction | ClassExpression>node);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return getJSDocTypedefTagName(<JSDocTypedefTag>node);
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
@@ -460,31 +458,11 @@ namespace ts.NavigationBar {
|
||||
return "()";
|
||||
case SyntaxKind.IndexSignature:
|
||||
return "[]";
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return getJSDocTypedefTagName(<JSDocTypedefTag>node);
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
function getJSDocTypedefTagName(node: JSDocTypedefTag): string {
|
||||
if (node.name) {
|
||||
return node.name.text;
|
||||
}
|
||||
else {
|
||||
const parentNode = node.parent && node.parent.parent;
|
||||
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
|
||||
if (parentNode.declarationList.declarations.length > 0) {
|
||||
const nameIdentifier = parentNode.declarationList.declarations[0].name;
|
||||
if (nameIdentifier.kind === SyntaxKind.Identifier) {
|
||||
return nameIdentifier.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "<typedef>";
|
||||
}
|
||||
}
|
||||
|
||||
/** Flattens the NavNode tree to a list, keeping only the top-level items. */
|
||||
function topLevelItems(root: NavigationBarNode): NavigationBarNode[] {
|
||||
const topLevel: NavigationBarNode[] = [];
|
||||
@@ -511,6 +489,7 @@ namespace ts.NavigationBar {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return true;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
|
||||
@@ -1464,8 +1464,8 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
|
||||
// Note that we add the current node's type parameters *after* updating the corresponding scope.
|
||||
if (isDeclarationWithTypeParameters(curr) && curr.typeParameters) {
|
||||
for (const typeParameterDecl of curr.typeParameters) {
|
||||
if (isDeclarationWithTypeParameters(curr) && getEffectiveTypeParameterDeclarations(curr)) {
|
||||
for (const typeParameterDecl of getEffectiveTypeParameterDeclarations(curr)) {
|
||||
const typeParameter = checker.getTypeAtLocation(typeParameterDecl) as TypeParameter;
|
||||
if (allTypeParameterUsages.has(typeParameter.id.toString())) {
|
||||
seenTypeParameterUsages.set(typeParameter.id.toString(), typeParameter);
|
||||
@@ -1536,8 +1536,8 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
function hasTypeParameters(node: Node) {
|
||||
return isDeclarationWithTypeParameters(node) &&
|
||||
node.typeParameters !== undefined &&
|
||||
node.typeParameters.length > 0;
|
||||
getEffectiveTypeParameterDeclarations(node) &&
|
||||
getEffectiveTypeParameterDeclarations(node).length > 0;
|
||||
}
|
||||
|
||||
function isInGenericContext(node: Node) {
|
||||
|
||||
@@ -276,7 +276,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getContainerNode(node: Node): Declaration {
|
||||
if (node.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
if (isJSDocTypeAlias(node)) {
|
||||
// This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope.
|
||||
// node.parent = the JSDoc comment, node.parent.parent = the node having the comment.
|
||||
// Then we get parent again in the loop.
|
||||
@@ -315,7 +315,10 @@ namespace ts {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return ScriptElementKind.classElement;
|
||||
case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement;
|
||||
case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement;
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return ScriptElementKind.typeElement;
|
||||
case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement;
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return getKindOfVariableDeclaration(<VariableDeclaration>node);
|
||||
@@ -346,8 +349,6 @@ namespace ts {
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return ScriptElementKind.alias;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return ScriptElementKind.typeElement;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
const kind = getSpecialPropertyAssignmentKind(node as BinaryExpression);
|
||||
const { right } = node as BinaryExpression;
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"typeExpression": {
|
||||
"kind": "JSDocTypeLiteral",
|
||||
"pos": 26,
|
||||
"pos": 28,
|
||||
"end": 98,
|
||||
"jsDocPropertyTags": [
|
||||
{
|
||||
|
||||
+38
-21
@@ -349,22 +349,24 @@ declare namespace ts {
|
||||
JSDocVariadicType = 284,
|
||||
JSDocComment = 285,
|
||||
JSDocTypeLiteral = 286,
|
||||
JSDocTag = 287,
|
||||
JSDocAugmentsTag = 288,
|
||||
JSDocClassTag = 289,
|
||||
JSDocParameterTag = 290,
|
||||
JSDocReturnTag = 291,
|
||||
JSDocTypeTag = 292,
|
||||
JSDocTemplateTag = 293,
|
||||
JSDocTypedefTag = 294,
|
||||
JSDocPropertyTag = 295,
|
||||
SyntaxList = 296,
|
||||
NotEmittedStatement = 297,
|
||||
PartiallyEmittedExpression = 298,
|
||||
CommaListExpression = 299,
|
||||
MergeDeclarationMarker = 300,
|
||||
EndOfDeclarationMarker = 301,
|
||||
Count = 302,
|
||||
JSDocSignature = 287,
|
||||
JSDocTag = 288,
|
||||
JSDocAugmentsTag = 289,
|
||||
JSDocClassTag = 290,
|
||||
JSDocCallbackTag = 291,
|
||||
JSDocParameterTag = 292,
|
||||
JSDocReturnTag = 293,
|
||||
JSDocTypeTag = 294,
|
||||
JSDocTemplateTag = 295,
|
||||
JSDocTypedefTag = 296,
|
||||
JSDocPropertyTag = 297,
|
||||
SyntaxList = 298,
|
||||
NotEmittedStatement = 299,
|
||||
PartiallyEmittedExpression = 300,
|
||||
CommaListExpression = 301,
|
||||
MergeDeclarationMarker = 302,
|
||||
EndOfDeclarationMarker = 303,
|
||||
Count = 304,
|
||||
FirstAssignment = 58,
|
||||
LastAssignment = 70,
|
||||
FirstCompoundAssignment = 59,
|
||||
@@ -391,9 +393,9 @@ declare namespace ts {
|
||||
LastBinaryOperator = 70,
|
||||
FirstNode = 145,
|
||||
FirstJSDocNode = 277,
|
||||
LastJSDocNode = 295,
|
||||
FirstJSDocTagNode = 287,
|
||||
LastJSDocTagNode = 295
|
||||
LastJSDocNode = 297,
|
||||
FirstJSDocTagNode = 288,
|
||||
LastJSDocTagNode = 297
|
||||
}
|
||||
enum NodeFlags {
|
||||
None = 0,
|
||||
@@ -1280,7 +1282,7 @@ declare namespace ts {
|
||||
block: Block;
|
||||
}
|
||||
type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
|
||||
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
|
||||
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
|
||||
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
|
||||
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
|
||||
name?: Identifier;
|
||||
@@ -1537,6 +1539,19 @@ declare namespace ts {
|
||||
name?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression | JSDocTypeLiteral;
|
||||
}
|
||||
interface JSDocCallbackTag extends JSDocTag, NamedDeclaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocCallbackTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
typeExpression: JSDocSignature;
|
||||
}
|
||||
interface JSDocSignature extends JSDocType, Declaration {
|
||||
kind: SyntaxKind.JSDocSignature;
|
||||
typeParameters?: ReadonlyArray<JSDocTemplateTag>;
|
||||
parameters: ReadonlyArray<JSDocParameterTag>;
|
||||
type: JSDocReturnTag | undefined;
|
||||
}
|
||||
interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
name: EntityName;
|
||||
@@ -2283,7 +2298,7 @@ declare namespace ts {
|
||||
Construct = 1
|
||||
}
|
||||
interface Signature {
|
||||
declaration?: SignatureDeclaration;
|
||||
declaration?: SignatureDeclaration | JSDocSignature;
|
||||
typeParameters?: TypeParameter[];
|
||||
parameters: Symbol[];
|
||||
}
|
||||
@@ -3362,6 +3377,8 @@ declare namespace ts {
|
||||
function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag;
|
||||
function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag;
|
||||
function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral;
|
||||
function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag;
|
||||
function isJSDocSignature(node: Node): node is JSDocSignature;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
|
||||
+38
-21
@@ -349,22 +349,24 @@ declare namespace ts {
|
||||
JSDocVariadicType = 284,
|
||||
JSDocComment = 285,
|
||||
JSDocTypeLiteral = 286,
|
||||
JSDocTag = 287,
|
||||
JSDocAugmentsTag = 288,
|
||||
JSDocClassTag = 289,
|
||||
JSDocParameterTag = 290,
|
||||
JSDocReturnTag = 291,
|
||||
JSDocTypeTag = 292,
|
||||
JSDocTemplateTag = 293,
|
||||
JSDocTypedefTag = 294,
|
||||
JSDocPropertyTag = 295,
|
||||
SyntaxList = 296,
|
||||
NotEmittedStatement = 297,
|
||||
PartiallyEmittedExpression = 298,
|
||||
CommaListExpression = 299,
|
||||
MergeDeclarationMarker = 300,
|
||||
EndOfDeclarationMarker = 301,
|
||||
Count = 302,
|
||||
JSDocSignature = 287,
|
||||
JSDocTag = 288,
|
||||
JSDocAugmentsTag = 289,
|
||||
JSDocClassTag = 290,
|
||||
JSDocCallbackTag = 291,
|
||||
JSDocParameterTag = 292,
|
||||
JSDocReturnTag = 293,
|
||||
JSDocTypeTag = 294,
|
||||
JSDocTemplateTag = 295,
|
||||
JSDocTypedefTag = 296,
|
||||
JSDocPropertyTag = 297,
|
||||
SyntaxList = 298,
|
||||
NotEmittedStatement = 299,
|
||||
PartiallyEmittedExpression = 300,
|
||||
CommaListExpression = 301,
|
||||
MergeDeclarationMarker = 302,
|
||||
EndOfDeclarationMarker = 303,
|
||||
Count = 304,
|
||||
FirstAssignment = 58,
|
||||
LastAssignment = 70,
|
||||
FirstCompoundAssignment = 59,
|
||||
@@ -391,9 +393,9 @@ declare namespace ts {
|
||||
LastBinaryOperator = 70,
|
||||
FirstNode = 145,
|
||||
FirstJSDocNode = 277,
|
||||
LastJSDocNode = 295,
|
||||
FirstJSDocTagNode = 287,
|
||||
LastJSDocTagNode = 295
|
||||
LastJSDocNode = 297,
|
||||
FirstJSDocTagNode = 288,
|
||||
LastJSDocTagNode = 297
|
||||
}
|
||||
enum NodeFlags {
|
||||
None = 0,
|
||||
@@ -1280,7 +1282,7 @@ declare namespace ts {
|
||||
block: Block;
|
||||
}
|
||||
type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
|
||||
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
|
||||
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
|
||||
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
|
||||
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
|
||||
name?: Identifier;
|
||||
@@ -1537,6 +1539,19 @@ declare namespace ts {
|
||||
name?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression | JSDocTypeLiteral;
|
||||
}
|
||||
interface JSDocCallbackTag extends JSDocTag, NamedDeclaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocCallbackTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
typeExpression: JSDocSignature;
|
||||
}
|
||||
interface JSDocSignature extends JSDocType, Declaration {
|
||||
kind: SyntaxKind.JSDocSignature;
|
||||
typeParameters?: ReadonlyArray<JSDocTemplateTag>;
|
||||
parameters: ReadonlyArray<JSDocParameterTag>;
|
||||
type: JSDocReturnTag | undefined;
|
||||
}
|
||||
interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
name: EntityName;
|
||||
@@ -2283,7 +2298,7 @@ declare namespace ts {
|
||||
Construct = 1
|
||||
}
|
||||
interface Signature {
|
||||
declaration?: SignatureDeclaration;
|
||||
declaration?: SignatureDeclaration | JSDocSignature;
|
||||
typeParameters?: TypeParameter[];
|
||||
parameters: Symbol[];
|
||||
}
|
||||
@@ -3362,6 +3377,8 @@ declare namespace ts {
|
||||
function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag;
|
||||
function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag;
|
||||
function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral;
|
||||
function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag;
|
||||
function isJSDocSignature(node: Node): node is JSDocSignature;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
=== tests/cases/conformance/jsdoc/mod1.js ===
|
||||
/** @callback Con - some kind of continuation
|
||||
* @param {object | undefined} error
|
||||
* @return {any} I don't even know what this should return
|
||||
*/
|
||||
module.exports = C
|
||||
>module : Symbol(export=, Decl(mod1.js, 0, 0))
|
||||
>exports : Symbol(export=, Decl(mod1.js, 0, 0))
|
||||
>C : Symbol(C, Decl(mod1.js, 4, 18))
|
||||
|
||||
function C() {
|
||||
>C : Symbol(C, Decl(mod1.js, 4, 18))
|
||||
|
||||
this.p = 1
|
||||
>p : Symbol(C.p, Decl(mod1.js, 5, 14))
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/jsdoc/use.js ===
|
||||
/** @param {import('./mod1').Con} k */
|
||||
function f(k) {
|
||||
>f : Symbol(f, Decl(use.js, 0, 0))
|
||||
>k : Symbol(k, Decl(use.js, 1, 11))
|
||||
|
||||
if (1 === 2 - 1) {
|
||||
// I guess basic math works!
|
||||
}
|
||||
return k({ ok: true})
|
||||
>k : Symbol(k, Decl(use.js, 1, 11))
|
||||
>ok : Symbol(ok, Decl(use.js, 5, 14))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/conformance/jsdoc/mod1.js ===
|
||||
/** @callback Con - some kind of continuation
|
||||
* @param {object | undefined} error
|
||||
* @return {any} I don't even know what this should return
|
||||
*/
|
||||
module.exports = C
|
||||
>module.exports = C : typeof C
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>C : typeof C
|
||||
|
||||
function C() {
|
||||
>C : typeof C
|
||||
|
||||
this.p = 1
|
||||
>this.p = 1 : 1
|
||||
>this.p : any
|
||||
>this : any
|
||||
>p : any
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/jsdoc/use.js ===
|
||||
/** @param {import('./mod1').Con} k */
|
||||
function f(k) {
|
||||
>f : (k: (error: any) => any) => any
|
||||
>k : (error: any) => any
|
||||
|
||||
if (1 === 2 - 1) {
|
||||
>1 === 2 - 1 : boolean
|
||||
>1 : 1
|
||||
>2 - 1 : number
|
||||
>2 : 2
|
||||
>1 : 1
|
||||
|
||||
// I guess basic math works!
|
||||
}
|
||||
return k({ ok: true})
|
||||
>k({ ok: true}) : any
|
||||
>k : (error: any) => any
|
||||
>{ ok: true} : { ok: boolean; }
|
||||
>ok : boolean
|
||||
>true : true
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @callback Sid
|
||||
* @param {string} s
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
var x = 1
|
||||
>x : Symbol(x, Decl(cb.js, 4, 3))
|
||||
|
||||
/** @type {Sid} smallId */
|
||||
var sid = s => s + "!";
|
||||
>sid : Symbol(sid, Decl(cb.js, 7, 3))
|
||||
>s : Symbol(s, Decl(cb.js, 7, 9))
|
||||
>s : Symbol(s, Decl(cb.js, 7, 9))
|
||||
|
||||
|
||||
/** @type {NoReturn} */
|
||||
var noreturn = obj => void obj.title
|
||||
>noreturn : Symbol(noreturn, Decl(cb.js, 11, 3))
|
||||
>obj : Symbol(obj, Decl(cb.js, 11, 14))
|
||||
>obj.title : Symbol(title, Decl(cb.js, 15, 34))
|
||||
>obj : Symbol(obj, Decl(cb.js, 11, 14))
|
||||
>title : Symbol(title, Decl(cb.js, 15, 34))
|
||||
|
||||
/**
|
||||
* @callback NoReturn
|
||||
* @param {{ e: number, m: number, title: string }} s - Knee deep, shores, etc
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @callback Sid
|
||||
* @param {string} s
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
var x = 1
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
/** @type {Sid} smallId */
|
||||
var sid = s => s + "!";
|
||||
>sid : Sid
|
||||
>s => s + "!" : (s: string) => string
|
||||
>s : string
|
||||
>s + "!" : string
|
||||
>s : string
|
||||
>"!" : "!"
|
||||
|
||||
|
||||
/** @type {NoReturn} */
|
||||
var noreturn = obj => void obj.title
|
||||
>noreturn : (s: { e: number; m: number; title: string; }) => any
|
||||
>obj => void obj.title : (obj: { e: number; m: number; title: string; }) => any
|
||||
>obj : { e: number; m: number; title: string; }
|
||||
>void obj.title : undefined
|
||||
>obj.title : string
|
||||
>obj : { e: number; m: number; title: string; }
|
||||
>title : string
|
||||
|
||||
/**
|
||||
* @callback NoReturn
|
||||
* @param {{ e: number, m: number, title: string }} s - Knee deep, shores, etc
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
tests/cases/conformance/jsdoc/cb.js(18,29): error TS2304: Cannot find name 'S'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/cb.js (1 errors) ====
|
||||
/** @template T
|
||||
* @callback Id
|
||||
* @param {T} t
|
||||
* @returns {T} Maybe just return 120 and cast it?
|
||||
*/
|
||||
var x = 1
|
||||
|
||||
/** @type {Id<string>} I actually wanted to write `const "120"` */
|
||||
var one_twenty = s => "120";
|
||||
|
||||
/** @template S
|
||||
* @callback SharedId
|
||||
* @param {S} ego
|
||||
* @return {S}
|
||||
*/
|
||||
class SharedClass {
|
||||
constructor() {
|
||||
/** @type {SharedId<S>} */
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'S'.
|
||||
this.id;
|
||||
}
|
||||
}
|
||||
/** @type {SharedId<number>} */
|
||||
var outside = n => n + 1;
|
||||
|
||||
/** @type {Final<{ fantasy }, { heroes }>} */
|
||||
var noreturn = (barts, tidus, noctis) => "cecil"
|
||||
|
||||
/**
|
||||
* @template V,X
|
||||
* @callback Final
|
||||
* @param {V} barts - "Barts"
|
||||
* @param {X} tidus - Titus
|
||||
* @param {X & V} noctis - "Prince Noctis Lucius Caelum"
|
||||
* @return {"cecil" | "zidane"}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @template T
|
||||
* @callback Id
|
||||
* @param {T} t
|
||||
* @returns {T} Maybe just return 120 and cast it?
|
||||
*/
|
||||
var x = 1
|
||||
>x : Symbol(x, Decl(cb.js, 5, 3))
|
||||
|
||||
/** @type {Id<string>} I actually wanted to write `const "120"` */
|
||||
var one_twenty = s => "120";
|
||||
>one_twenty : Symbol(one_twenty, Decl(cb.js, 8, 3))
|
||||
>s : Symbol(s, Decl(cb.js, 8, 16))
|
||||
|
||||
/** @template S
|
||||
* @callback SharedId
|
||||
* @param {S} ego
|
||||
* @return {S}
|
||||
*/
|
||||
class SharedClass {
|
||||
>SharedClass : Symbol(SharedClass, Decl(cb.js, 8, 28))
|
||||
|
||||
constructor() {
|
||||
/** @type {SharedId<S>} */
|
||||
this.id;
|
||||
>this.id : Symbol(SharedClass.id, Decl(cb.js, 16, 19))
|
||||
>this : Symbol(SharedClass, Decl(cb.js, 8, 28))
|
||||
>id : Symbol(SharedClass.id, Decl(cb.js, 16, 19))
|
||||
}
|
||||
}
|
||||
/** @type {SharedId<number>} */
|
||||
var outside = n => n + 1;
|
||||
>outside : Symbol(outside, Decl(cb.js, 22, 3))
|
||||
>n : Symbol(n, Decl(cb.js, 22, 13))
|
||||
>n : Symbol(n, Decl(cb.js, 22, 13))
|
||||
|
||||
/** @type {Final<{ fantasy }, { heroes }>} */
|
||||
var noreturn = (barts, tidus, noctis) => "cecil"
|
||||
>noreturn : Symbol(noreturn, Decl(cb.js, 25, 3))
|
||||
>barts : Symbol(barts, Decl(cb.js, 25, 16))
|
||||
>tidus : Symbol(tidus, Decl(cb.js, 25, 22))
|
||||
>noctis : Symbol(noctis, Decl(cb.js, 25, 29))
|
||||
|
||||
/**
|
||||
* @template V,X
|
||||
* @callback Final
|
||||
* @param {V} barts - "Barts"
|
||||
* @param {X} tidus - Titus
|
||||
* @param {X & V} noctis - "Prince Noctis Lucius Caelum"
|
||||
* @return {"cecil" | "zidane"}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @template T
|
||||
* @callback Id
|
||||
* @param {T} t
|
||||
* @returns {T} Maybe just return 120 and cast it?
|
||||
*/
|
||||
var x = 1
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
/** @type {Id<string>} I actually wanted to write `const "120"` */
|
||||
var one_twenty = s => "120";
|
||||
>one_twenty : Id<string>
|
||||
>s => "120" : (s: string) => string
|
||||
>s : string
|
||||
>"120" : "120"
|
||||
|
||||
/** @template S
|
||||
* @callback SharedId
|
||||
* @param {S} ego
|
||||
* @return {S}
|
||||
*/
|
||||
class SharedClass {
|
||||
>SharedClass : SharedClass
|
||||
|
||||
constructor() {
|
||||
/** @type {SharedId<S>} */
|
||||
this.id;
|
||||
>this.id : SharedId<any>
|
||||
>this : this
|
||||
>id : SharedId<any>
|
||||
}
|
||||
}
|
||||
/** @type {SharedId<number>} */
|
||||
var outside = n => n + 1;
|
||||
>outside : SharedId<number>
|
||||
>n => n + 1 : (n: number) => number
|
||||
>n : number
|
||||
>n + 1 : number
|
||||
>n : number
|
||||
>1 : 1
|
||||
|
||||
/** @type {Final<{ fantasy }, { heroes }>} */
|
||||
var noreturn = (barts, tidus, noctis) => "cecil"
|
||||
>noreturn : (barts: { fantasy: any; }, tidus: { heroes: any; }, noctis: { heroes: any; } & { fantasy: any; }) => "cecil" | "zidane"
|
||||
>(barts, tidus, noctis) => "cecil" : (barts: { fantasy: any; }, tidus: { heroes: any; }, noctis: { heroes: any; } & { fantasy: any; }) => "cecil"
|
||||
>barts : { fantasy: any; }
|
||||
>tidus : { heroes: any; }
|
||||
>noctis : { heroes: any; } & { fantasy: any; }
|
||||
>"cecil" : "cecil"
|
||||
|
||||
/**
|
||||
* @template V,X
|
||||
* @callback Final
|
||||
* @param {V} barts - "Barts"
|
||||
* @param {X} tidus - Titus
|
||||
* @param {X & V} noctis - "Prince Noctis Lucius Caelum"
|
||||
* @return {"cecil" | "zidane"}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @callback Miracle
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
/** @type {Miracle} smallId */
|
||||
var sid = () => "!";
|
||||
>sid : Symbol(sid, Decl(cb.js, 4, 3))
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/conformance/jsdoc/cb.js ===
|
||||
/** @callback Miracle
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
/** @type {Miracle} smallId */
|
||||
var sid = () => "!";
|
||||
>sid : Miracle
|
||||
>() => "!" : () => string
|
||||
>"!" : "!"
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/jsdoc/namespaced.js ===
|
||||
/**
|
||||
* @callback NS.Nested.Inner
|
||||
* @param {string} space - spaaaaaaaaace
|
||||
* @param {string} peace - peaaaaaaaaace
|
||||
* @return {string | number}
|
||||
*/
|
||||
var x = 1;
|
||||
>x : Symbol(x, Decl(namespaced.js, 6, 3))
|
||||
|
||||
/** @type {NS.Nested.Inner} */
|
||||
function f(space, peace) {
|
||||
>f : Symbol(f, Decl(namespaced.js, 6, 10))
|
||||
>space : Symbol(space, Decl(namespaced.js, 8, 11))
|
||||
>peace : Symbol(peace, Decl(namespaced.js, 8, 17))
|
||||
|
||||
return '1'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
=== tests/cases/conformance/jsdoc/namespaced.js ===
|
||||
/**
|
||||
* @callback NS.Nested.Inner
|
||||
* @param {string} space - spaaaaaaaaace
|
||||
* @param {string} peace - peaaaaaaaaace
|
||||
* @return {string | number}
|
||||
*/
|
||||
var x = 1;
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
/** @type {NS.Nested.Inner} */
|
||||
function f(space, peace) {
|
||||
>f : (space: string, peace: string) => string
|
||||
>space : string
|
||||
>peace : string
|
||||
|
||||
return '1'
|
||||
>'1' : "1"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
tests/cases/conformance/jsdoc/templateTagOnClasses.js(24,1): error TS2322: Type 'boolean' is not assignable to type 'number'.
|
||||
tests/cases/conformance/jsdoc/templateTagOnClasses.js(25,1): error TS2322: Type 'boolean' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/templateTagOnClasses.js (1 errors) ====
|
||||
@@ -6,6 +6,7 @@ tests/cases/conformance/jsdoc/templateTagOnClasses.js(24,1): error TS2322: Type
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
*/
|
||||
/** @template T */
|
||||
class Foo {
|
||||
/** @typedef {(t: T) => T} Id2 */
|
||||
/** @param {T} x */
|
||||
@@ -15,7 +16,7 @@ tests/cases/conformance/jsdoc/templateTagOnClasses.js(24,1): error TS2322: Type
|
||||
/**
|
||||
*
|
||||
* @param {T} x
|
||||
* @param {Id} y
|
||||
* @param {Id<T>} y
|
||||
* @param {Id2} alpha
|
||||
* @return {T}
|
||||
*/
|
||||
|
||||
@@ -3,52 +3,53 @@
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
*/
|
||||
/** @template T */
|
||||
class Foo {
|
||||
>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0))
|
||||
|
||||
/** @typedef {(t: T) => T} Id2 */
|
||||
/** @param {T} x */
|
||||
constructor (x) {
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 7, 17))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 8, 17))
|
||||
|
||||
this.a = x
|
||||
>this.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>this.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
>this : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 7, 17))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 8, 17))
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {T} x
|
||||
* @param {Id} y
|
||||
* @param {Id<T>} y
|
||||
* @param {Id2} alpha
|
||||
* @return {T}
|
||||
*/
|
||||
foo(x, y, alpha) {
|
||||
>foo : Symbol(Foo.foo, Decl(templateTagOnClasses.js, 9, 5))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 17, 8))
|
||||
>y : Symbol(y, Decl(templateTagOnClasses.js, 17, 10))
|
||||
>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 17, 13))
|
||||
>foo : Symbol(Foo.foo, Decl(templateTagOnClasses.js, 10, 5))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 18, 8))
|
||||
>y : Symbol(y, Decl(templateTagOnClasses.js, 18, 10))
|
||||
>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 18, 13))
|
||||
|
||||
return alpha(y(x))
|
||||
>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 17, 13))
|
||||
>y : Symbol(y, Decl(templateTagOnClasses.js, 17, 10))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 17, 8))
|
||||
>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 18, 13))
|
||||
>y : Symbol(y, Decl(templateTagOnClasses.js, 18, 10))
|
||||
>x : Symbol(x, Decl(templateTagOnClasses.js, 18, 8))
|
||||
}
|
||||
}
|
||||
var f = new Foo(1)
|
||||
>f : Symbol(f, Decl(templateTagOnClasses.js, 21, 3))
|
||||
>f : Symbol(f, Decl(templateTagOnClasses.js, 22, 3))
|
||||
>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0))
|
||||
|
||||
var g = new Foo(false)
|
||||
>g : Symbol(g, Decl(templateTagOnClasses.js, 22, 3))
|
||||
>g : Symbol(g, Decl(templateTagOnClasses.js, 23, 3))
|
||||
>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0))
|
||||
|
||||
f.a = g.a
|
||||
>f.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>f : Symbol(f, Decl(templateTagOnClasses.js, 21, 3))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>g.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>g : Symbol(g, Decl(templateTagOnClasses.js, 22, 3))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21))
|
||||
>f.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
>f : Symbol(f, Decl(templateTagOnClasses.js, 22, 3))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
>g.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
>g : Symbol(g, Decl(templateTagOnClasses.js, 23, 3))
|
||||
>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 8, 21))
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
*/
|
||||
/** @template T */
|
||||
class Foo {
|
||||
>Foo : Foo<T>
|
||||
|
||||
@@ -21,7 +22,7 @@ class Foo {
|
||||
/**
|
||||
*
|
||||
* @param {T} x
|
||||
* @param {Id} y
|
||||
* @param {Id<T>} y
|
||||
* @param {Id2} alpha
|
||||
* @return {T}
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js(21,1): error TS2322: Type 'false' is not assignable to type 'number'.
|
||||
tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js(24,1): error TS2322: Type 'false' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js (1 errors) ====
|
||||
/**
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
* @template {U}
|
||||
* @typedef {(u: U) => U} Id
|
||||
*/
|
||||
/**
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
/** @type {T} */
|
||||
@@ -14,7 +17,7 @@ tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js(21,1): error
|
||||
}
|
||||
/**
|
||||
* @param {T} v
|
||||
* @param {Id} id
|
||||
* @param {Id<T>} id
|
||||
*/
|
||||
Zet.prototype.add = function(v, id) {
|
||||
this.u = v || this.t
|
||||
|
||||
@@ -1,57 +1,60 @@
|
||||
=== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js ===
|
||||
/**
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
* @template {U}
|
||||
* @typedef {(u: U) => U} Id
|
||||
*/
|
||||
/**
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 5, 13))
|
||||
>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 8, 13))
|
||||
|
||||
/** @type {T} */
|
||||
this.u
|
||||
this.t = t
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10))
|
||||
>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 5, 13))
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 10, 10))
|
||||
>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 8, 13))
|
||||
}
|
||||
/**
|
||||
* @param {T} v
|
||||
* @param {Id} id
|
||||
* @param {Id<T>} id
|
||||
*/
|
||||
Zet.prototype.add = function(v, id) {
|
||||
>Zet.prototype : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 9, 1))
|
||||
>Zet.prototype : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 12, 1))
|
||||
>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --))
|
||||
>add : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 9, 1))
|
||||
>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 14, 29))
|
||||
>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 14, 31))
|
||||
>add : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 12, 1))
|
||||
>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 17, 29))
|
||||
>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 17, 31))
|
||||
|
||||
this.u = v || this.t
|
||||
>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 14, 29))
|
||||
>this.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 17, 29))
|
||||
>this.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 10, 10))
|
||||
>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10))
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 10, 10))
|
||||
|
||||
return id(this.u)
|
||||
>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 14, 31))
|
||||
>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 17, 31))
|
||||
>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
}
|
||||
var z = new Zet(1)
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3))
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 21, 3))
|
||||
>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0))
|
||||
|
||||
z.t = 2
|
||||
>z.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10))
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3))
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10))
|
||||
>z.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 10, 10))
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 21, 3))
|
||||
>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 10, 10))
|
||||
|
||||
z.u = false
|
||||
>z.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37))
|
||||
>z.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 21, 3))
|
||||
>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 8, 17), Decl(templateTagOnConstructorFunctions.js, 17, 37))
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
=== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js ===
|
||||
/**
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
* @template {U}
|
||||
* @typedef {(u: U) => U} Id
|
||||
*/
|
||||
/**
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
>Zet : typeof Zet
|
||||
@@ -23,18 +26,18 @@ function Zet(t) {
|
||||
}
|
||||
/**
|
||||
* @param {T} v
|
||||
* @param {Id} id
|
||||
* @param {Id<T>} id
|
||||
*/
|
||||
Zet.prototype.add = function(v, id) {
|
||||
>Zet.prototype.add = function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (t: T) => T) => T
|
||||
>Zet.prototype.add = function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (u: T) => T) => T
|
||||
>Zet.prototype.add : any
|
||||
>Zet.prototype : any
|
||||
>Zet : typeof Zet
|
||||
>prototype : any
|
||||
>add : any
|
||||
>function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (t: T) => T) => T
|
||||
>function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (u: T) => T) => T
|
||||
>v : T
|
||||
>id : (t: T) => T
|
||||
>id : (u: T) => T
|
||||
|
||||
this.u = v || this.t
|
||||
>this.u = v || this.t : T
|
||||
@@ -49,7 +52,7 @@ Zet.prototype.add = function(v, id) {
|
||||
|
||||
return id(this.u)
|
||||
>id(this.u) : T
|
||||
>id : (t: T) => T
|
||||
>id : (u: T) => T
|
||||
>this.u : T
|
||||
>this : Zet
|
||||
>u : T
|
||||
|
||||
@@ -4,8 +4,8 @@ tests/cases/conformance/jsdoc/templateTagWithNestedTypeLiteral.js(26,15): error
|
||||
|
||||
==== tests/cases/conformance/jsdoc/templateTagWithNestedTypeLiteral.js (2 errors) ====
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
/** @type {T} */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
=== tests/cases/conformance/jsdoc/templateTagWithNestedTypeLiteral.js ===
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
>Zet : Symbol(Zet, Decl(templateTagWithNestedTypeLiteral.js, 0, 0))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
=== tests/cases/conformance/jsdoc/templateTagWithNestedTypeLiteral.js ===
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
>Zet : typeof Zet
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/jsdoc/github17339.js ===
|
||||
var obj = {
|
||||
>obj : Symbol(obj, Decl(github17339.js, 0, 3))
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @returns {T}
|
||||
*/
|
||||
x: function (a) {
|
||||
>x : Symbol(x, Decl(github17339.js, 0, 11))
|
||||
>a : Symbol(a, Decl(github17339.js, 6, 14))
|
||||
|
||||
return a;
|
||||
>a : Symbol(a, Decl(github17339.js, 6, 14))
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
=== tests/cases/conformance/jsdoc/github17339.js ===
|
||||
var obj = {
|
||||
>obj : { [x: string]: any; x: <T>(a: T) => T; }
|
||||
>{ /** * @template T * @param {T} a * @returns {T} */ x: function (a) { return a; },} : { [x: string]: any; x: <T>(a: T) => T; }
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @returns {T}
|
||||
*/
|
||||
x: function (a) {
|
||||
>x : <T>(a: T) => T
|
||||
>function (a) { return a; } : <T>(a: T) => T
|
||||
>a : T
|
||||
|
||||
return a;
|
||||
>a : T
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: mod1.js
|
||||
/** @callback Con - some kind of continuation
|
||||
* @param {object | undefined} error
|
||||
* @return {any} I don't even know what this should return
|
||||
*/
|
||||
module.exports = C
|
||||
function C() {
|
||||
this.p = 1
|
||||
}
|
||||
|
||||
// @Filename: use.js
|
||||
/** @param {import('./mod1').Con} k */
|
||||
function f(k) {
|
||||
if (1 === 2 - 1) {
|
||||
// I guess basic math works!
|
||||
}
|
||||
return k({ ok: true})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: cb.js
|
||||
|
||||
/** @callback Sid
|
||||
* @param {string} s
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
var x = 1
|
||||
|
||||
/** @type {Sid} smallId */
|
||||
var sid = s => s + "!";
|
||||
|
||||
|
||||
/** @type {NoReturn} */
|
||||
var noreturn = obj => void obj.title
|
||||
|
||||
/**
|
||||
* @callback NoReturn
|
||||
* @param {{ e: number, m: number, title: string }} s - Knee deep, shores, etc
|
||||
*/
|
||||
@@ -0,0 +1,40 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: cb.js
|
||||
|
||||
/** @template T
|
||||
* @callback Id
|
||||
* @param {T} t
|
||||
* @returns {T} Maybe just return 120 and cast it?
|
||||
*/
|
||||
var x = 1
|
||||
|
||||
/** @type {Id<string>} I actually wanted to write `const "120"` */
|
||||
var one_twenty = s => "120";
|
||||
|
||||
/** @template S
|
||||
* @callback SharedId
|
||||
* @param {S} ego
|
||||
* @return {S}
|
||||
*/
|
||||
class SharedClass {
|
||||
constructor() {
|
||||
/** @type {SharedId<S>} */
|
||||
this.id;
|
||||
}
|
||||
}
|
||||
/** @type {SharedId<number>} */
|
||||
var outside = n => n + 1;
|
||||
|
||||
/** @type {Final<{ fantasy }, { heroes }>} */
|
||||
var noreturn = (barts, tidus, noctis) => "cecil"
|
||||
|
||||
/**
|
||||
* @template V,X
|
||||
* @callback Final
|
||||
* @param {V} barts - "Barts"
|
||||
* @param {X} tidus - Titus
|
||||
* @param {X & V} noctis - "Prince Noctis Lucius Caelum"
|
||||
* @return {"cecil" | "zidane"}
|
||||
*/
|
||||
@@ -0,0 +1,10 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: cb.js
|
||||
/** @callback Miracle
|
||||
* @returns {string} What were you expecting
|
||||
*/
|
||||
/** @type {Miracle} smallId */
|
||||
var sid = () => "!";
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: namespaced.js
|
||||
/**
|
||||
* @callback NS.Nested.Inner
|
||||
* @param {string} space - spaaaaaaaaace
|
||||
* @param {string} peace - peaaaaaaaaace
|
||||
* @return {string | number}
|
||||
*/
|
||||
var x = 1;
|
||||
/** @type {NS.Nested.Inner} */
|
||||
function f(space, peace) {
|
||||
return '1'
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
*/
|
||||
/** @template T */
|
||||
class Foo {
|
||||
/** @typedef {(t: T) => T} Id2 */
|
||||
/** @param {T} x */
|
||||
@@ -16,7 +17,7 @@ class Foo {
|
||||
/**
|
||||
*
|
||||
* @param {T} x
|
||||
* @param {Id} y
|
||||
* @param {Id<T>} y
|
||||
* @param {Id2} alpha
|
||||
* @return {T}
|
||||
*/
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
// @Filename: templateTagOnConstructorFunctions.js
|
||||
|
||||
/**
|
||||
* @template {T}
|
||||
* @typedef {(t: T) => T} Id
|
||||
* @template {U}
|
||||
* @typedef {(u: U) => U} Id
|
||||
*/
|
||||
/**
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
/** @type {T} */
|
||||
@@ -15,7 +18,7 @@ function Zet(t) {
|
||||
}
|
||||
/**
|
||||
* @param {T} v
|
||||
* @param {Id} id
|
||||
* @param {Id<T>} id
|
||||
*/
|
||||
Zet.prototype.add = function(v, id) {
|
||||
this.u = v || this.t
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// @Filename: templateTagWithNestedTypeLiteral.js
|
||||
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {T} t
|
||||
* @template {T}
|
||||
*/
|
||||
function Zet(t) {
|
||||
/** @type {T} */
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @lib: dom,esnext
|
||||
// @Filename: github17339.js
|
||||
|
||||
var obj = {
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @returns {T}
|
||||
*/
|
||||
x: function (a) {
|
||||
return a;
|
||||
},
|
||||
};
|
||||
@@ -6,7 +6,7 @@
|
||||
////// Data table
|
||||
/////**
|
||||
//// @typedef DataTableThing
|
||||
//// @type {Thing}
|
||||
//// @type {Object}
|
||||
//// @property {function(TagCollection, Location, string, string, Infotable):void} AddDataTableEntries - (arg0: tags, arg1: location, arg2: source, arg3: sourceType, arg4: values) Add multiple data table entries.
|
||||
//// @property {function(TagCollection, Location, string, string, Infotable):string} AddDataTableEntry - (arg0: tags, arg1: location, arg2: source, arg3: sourceType, arg4: values) Add a new data table entry.
|
||||
//// @property {function(TagCollection, Location, string, string, Infotable):void} AddOrUpdateDataTableEntries - (arg0: tags, arg1: location, arg2: source, arg3: sourceType, arg4: values) Add or update multiple data table entries.
|
||||
@@ -206,7 +206,7 @@
|
||||
//// * Another thing
|
||||
//// * @type {SomeCallback}
|
||||
//// */
|
||||
////var another/*2*/Thing = function(a, b) {}
|
||||
////var anotherThing/*2*/ = function(a, b) {}
|
||||
|
||||
verify.quickInfoAt("1", "var doSomething: (dataTable: DataTableThing) => void", "Do something");
|
||||
verify.quickInfoAt("2", "var anotherThing: any", "Another thing"); // TODO: #23947
|
||||
verify.quickInfoAt("2", "var anotherThing: SomeCallback", "Another thing");
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/// <reference path="../fourslash.ts"/>
|
||||
|
||||
// @allowNonTsExtensions: true
|
||||
// @Filename: jsdocCallbackTag.js
|
||||
//// /**
|
||||
//// * @callback FooHandler - A kind of magic
|
||||
//// * @param {string} eventName - So many words
|
||||
//// * @param eventName2 {number | string} - Silence is golden
|
||||
//// * @param eventName3 - Osterreich mos def
|
||||
//// * @return {number} - DIVEKICK
|
||||
//// */
|
||||
//// /**
|
||||
//// * @type {FooHa/*8*/ndler} callback
|
||||
//// */
|
||||
//// var t/*1*/;
|
||||
////
|
||||
//// /**
|
||||
//// * @callback FooHandler2 - What, another one?
|
||||
//// * @param {string=} eventName - it keeps happening
|
||||
//// * @param {string} [eventName2] - i WARNED you dog
|
||||
//// */
|
||||
//// /**
|
||||
//// * @type {FooH/*3*/andler2} callback
|
||||
//// */
|
||||
//// var t2/*2*/;
|
||||
//// t(/*4*/"!", /*5*/12, /*6*/false);
|
||||
|
||||
goTo.marker("1");
|
||||
verify.quickInfoIs("var t: FooHandler");
|
||||
goTo.marker("2");
|
||||
verify.quickInfoIs("var t2: FooHandler2");
|
||||
goTo.marker("3");
|
||||
verify.quickInfoIs("type FooHandler2 = (eventName?: string, eventName2?: string) => any", "- What, another one?");
|
||||
goTo.marker("8");
|
||||
verify.quickInfoIs("type FooHandler = (eventName: string, eventName2: string | number, eventName3: any) => number", "- A kind of magic");
|
||||
verify.signatureHelp({
|
||||
marker: '4',
|
||||
text: "t(eventName: string, eventName2: string | number, eventName3: any): number",
|
||||
parameterDocComment: "- So many words",
|
||||
tags: [{ name: "callback", text: "FooHandler - A kind of magic" },
|
||||
{ name: "type", text: "{FooHandler} callback" }]
|
||||
});
|
||||
verify.signatureHelp({
|
||||
marker: '5',
|
||||
parameterDocComment: "- Silence is golden",
|
||||
tags: [{ name: "callback", text: "FooHandler - A kind of magic" },
|
||||
{ name: "type", text: "{FooHandler} callback" }]
|
||||
});
|
||||
verify.signatureHelp({
|
||||
marker: '6',
|
||||
parameterDocComment: "- Osterreich mos def",
|
||||
tags: [{ name: "callback", text: "FooHandler - A kind of magic" },
|
||||
{ name: "type", text: "{FooHandler} callback" }]
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="../fourslash.ts"/>
|
||||
|
||||
// @allowNonTsExtensions: true
|
||||
// @Filename: jsDocCallback.js
|
||||
|
||||
//// /**
|
||||
//// * @callback FooCallback
|
||||
//// * @param {string} eventName - What even is the navigation bar?
|
||||
//// */
|
||||
//// /** @type {FooCallback} */
|
||||
//// var t;
|
||||
|
||||
verify.navigationBar([
|
||||
{
|
||||
"text": "<global>",
|
||||
"kind": "script",
|
||||
"childItems": [
|
||||
{
|
||||
"text": "FooCallback",
|
||||
"kind": "type"
|
||||
},
|
||||
{
|
||||
"text": "t",
|
||||
"kind": "var"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "FooCallback",
|
||||
"kind": "type",
|
||||
"indent": 1
|
||||
}
|
||||
])
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="../fourslash.ts"/>
|
||||
|
||||
// @allowNonTsExtensions: true
|
||||
// @Filename: jsDocCallback.js
|
||||
////
|
||||
//// /**
|
||||
//// * @callback [|FooCallback|]
|
||||
//// * @param {string} eventName - Rename should work
|
||||
//// */
|
||||
////
|
||||
//// /** @type {/*1*/[|FooCallback|]} */
|
||||
//// var t;
|
||||
|
||||
const ranges = test.ranges();
|
||||
verify.renameLocations(ranges[0], { findInStrings: false, findInComments: true, ranges });
|
||||
@@ -6,7 +6,7 @@
|
||||
//// /** @typedef {(string | number)} NumberLike */
|
||||
////
|
||||
//// /**
|
||||
//// * @typedef Animal
|
||||
//// * @typedef Animal - think Giraffes
|
||||
//// * @type {Object}
|
||||
//// * @property {string} animalName
|
||||
//// * @property {number} animalAge
|
||||
@@ -36,7 +36,7 @@
|
||||
//// p.personName./*personName*/;
|
||||
//// p.personAge./*personAge*/;
|
||||
////
|
||||
//// /** @type {Animal} */
|
||||
//// /** @type {/*AnimalType*/Animal} */
|
||||
//// var a;a./*animal*/;
|
||||
//// a.animalName./*animalName*/;
|
||||
//// a.animalAge./*animalAge*/;
|
||||
@@ -85,4 +85,7 @@ verify.completionListContains('catAge');
|
||||
goTo.marker('catName');
|
||||
verify.completionListContains('charAt');
|
||||
goTo.marker('catAge');
|
||||
verify.completionListContains('toExponential');
|
||||
verify.completionListContains('toExponential');
|
||||
|
||||
goTo.marker("AnimalType");
|
||||
verify.quickInfoIs("type Animal = {\n animalName: string;\n animalAge: number;\n}", "- think Giraffes");
|
||||
|
||||
Reference in New Issue
Block a user