feat(41825): JSDoc equivalent of import * (#57207)

This commit is contained in:
Oleksandr T
2024-03-26 22:52:43 +02:00
committed by GitHub
parent a22aaf0ee7
commit 2de69b09c5
116 changed files with 2689 additions and 91 deletions
+47
View File
@@ -94,6 +94,7 @@ import {
getExpandoInitializer,
getHostSignatureFromJSDoc,
getImmediatelyInvokedFunctionExpression,
getJSDocHost,
getJSDocTypeTag,
getLeftmostAccessExpression,
getNameOfDeclaration,
@@ -229,6 +230,7 @@ import {
JSDocClassTag,
JSDocEnumTag,
JSDocFunctionType,
JSDocImportTag,
JSDocOverloadTag,
JSDocParameterTag,
JSDocPropertyLikeTag,
@@ -525,6 +527,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
var lastContainer: HasLocals;
var delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[];
var seenThisKeyword: boolean;
var jsDocImports: JSDocImportTag[];
// state used by control flow analysis
var currentFlow: FlowNode;
@@ -592,6 +595,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
file.symbolCount = symbolCount;
file.classifiableNames = classifiableNames;
delayedBindJSDocTypedefTag();
bindJSDocImports();
}
file = undefined!;
@@ -603,6 +607,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
blockScopeContainer = undefined!;
lastContainer = undefined!;
delayedTypeAliases = undefined!;
jsDocImports = undefined!;
seenThisKeyword = false;
currentFlow = undefined!;
currentBreakTarget = undefined;
@@ -1181,6 +1186,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
break;
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
case SyntaxKind.JSDocImportTag:
bindJSDocImportTag(node as JSDocImportTag);
break;
case SyntaxKind.SourceFile: {
bindEachFunctionsFirst((node as SourceFile).statements);
bind((node as SourceFile).endOfFileToken);
@@ -2065,6 +2073,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}
}
function bindJSDocImportTag(node: JSDocImportTag) {
bind(node.tagName);
if (typeof node.comment !== "string") {
bindEach(node.comment);
}
}
function bindOptionalExpression(node: Expression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
doWithConditionalBranches(bind, node, trueTarget, falseTarget);
if (!isOptionalChain(node) || isOutermostOptionalChain(node)) {
@@ -2443,6 +2459,35 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
currentFlow = saveCurrentFlow;
}
function bindJSDocImports() {
if (jsDocImports === undefined) {
return;
}
const saveContainer = container;
const saveLastContainer = lastContainer;
const saveBlockScopeContainer = blockScopeContainer;
const saveParent = parent;
const saveCurrentFlow = currentFlow;
for (const jsDocImportTag of jsDocImports) {
const host = getJSDocHost(jsDocImportTag);
const enclosingContainer = host ? getEnclosingContainer(host) as IsContainer | undefined : undefined;
const enclosingBlockScopeContainer = host ? getEnclosingBlockScopeContainer(host) as IsBlockScopedContainer | undefined : undefined;
container = enclosingContainer || file;
blockScopeContainer = enclosingBlockScopeContainer || file;
currentFlow = initFlowNode({ flags: FlowFlags.Start });
parent = jsDocImportTag;
bind(jsDocImportTag.importClause);
}
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
// check for reserved words used as identifiers in strict mode code, as well as `yield` or `await` in
// [Yield] or [Await] contexts, respectively.
@@ -2995,6 +3040,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
case SyntaxKind.JSDocOverloadTag:
return bind((node as JSDocOverloadTag).typeExpression);
case SyntaxKind.JSDocImportTag:
return (jsDocImports || (jsDocImports = [])).push(node as JSDocImportTag);
}
}
+26 -10
View File
@@ -11,8 +11,8 @@ import {
AmbientModuleDeclaration,
and,
AnonymousType,
AnyImportOrJsDocImport,
AnyImportOrReExport,
AnyImportSyntax,
append,
appendIfUnique,
ArrayBindingPattern,
@@ -581,6 +581,7 @@ import {
isJSDocCallbackTag,
isJSDocConstructSignature,
isJSDocFunctionType,
isJSDocImportTag,
isJSDocIndexSignature,
isJSDocLinkLike,
isJSDocMemberName,
@@ -770,6 +771,7 @@ import {
JSDocEnumTag,
JSDocFunctionType,
JSDocImplementsTag,
JSDocImportTag,
JSDocLink,
JSDocLinkCode,
JSDocLinkPlain,
@@ -3382,6 +3384,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocEnumTag:
case SyntaxKind.JSDocImportTag:
// js type aliases do not resolve names from their host, so skip past it
const root = getJSDocRoot(location);
if (root) {
@@ -3950,7 +3953,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|| (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || (getFunctionFlags(n) & FunctionFlags.AsyncGenerator)) ? "quit" : false));
}
function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {
function getAnyImportSyntax(node: Node): AnyImportOrJsDocImport | undefined {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return node as ImportEqualsDeclaration;
@@ -4288,8 +4291,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined {
const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!;
function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration | JSDocImportTag, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined {
const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration | JSDocImportTag).moduleSpecifier!;
const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier)!; // TODO: GH#18217
const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name;
if (!isIdentifier(name)) {
@@ -5014,6 +5017,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
? location
: (isModuleDeclaration(location) ? location : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name ||
(isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal ||
(isInJSFile(location) && isJSDocImportTag(location) ? location.moduleSpecifier : undefined) ||
(isVariableDeclaration(location) && location.initializer && isRequireCall(location.initializer, /*requireStringLiteralLikeArgument*/ true) ? location.initializer.arguments[0] : undefined) ||
findAncestor(location, isImportCall)?.arguments[0] ||
findAncestor(location, isImportDeclaration)?.moduleSpecifier ||
@@ -9800,12 +9804,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.ImportClause: {
const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects
const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as ImportClause).parent.moduleSpecifier;
const attributes = isImportDeclaration(node.parent) ? node.parent.attributes : undefined;
const isTypeOnly = isJSDocImportTag((node as ImportClause).parent);
addResult(
factory.createImportDeclaration(
/*modifiers*/ undefined,
factory.createImportClause(/*isTypeOnly*/ false, factory.createIdentifier(localName), /*namedBindings*/ undefined),
factory.createImportClause(isTypeOnly, factory.createIdentifier(localName), /*namedBindings*/ undefined),
specifier,
(node as ImportClause).parent.attributes,
attributes,
),
ModifierFlags.None,
);
@@ -9814,10 +9820,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.NamespaceImport: {
const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects
const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as NamespaceImport).parent.parent.moduleSpecifier;
const isTypeOnly = isJSDocImportTag((node as NamespaceImport).parent.parent);
addResult(
factory.createImportDeclaration(
/*modifiers*/ undefined,
factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))),
factory.createImportClause(isTypeOnly, /*name*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))),
specifier,
(node as ImportClause).parent.attributes,
),
@@ -9839,11 +9846,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.ImportSpecifier: {
const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects
const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as ImportSpecifier).parent.parent.parent.moduleSpecifier;
const isTypeOnly = isJSDocImportTag((node as ImportSpecifier).parent.parent.parent);
addResult(
factory.createImportDeclaration(
/*modifiers*/ undefined,
factory.createImportClause(
/*isTypeOnly*/ false,
isTypeOnly,
/*name*/ undefined,
factory.createNamedImports([
factory.createImportSpecifier(
@@ -42193,6 +42201,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function checkJSDocImportTag(node: JSDocImportTag) {
checkImportAttributes(node);
}
function checkJSDocImplementsTag(node: JSDocImplementsTag): void {
const classLike = getEffectiveJSDocHost(node);
if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) {
@@ -46402,7 +46414,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function checkImportAttributes(declaration: ImportDeclaration | ExportDeclaration) {
function checkImportAttributes(declaration: ImportDeclaration | ExportDeclaration | JSDocImportTag) {
const node = declaration.attributes;
if (node) {
const importAttributesType = getGlobalImportAttributesType(/*reportErrors*/ true);
@@ -46429,7 +46441,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return grammarErrorOnNode(node, message);
}
if (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) {
const isTypeOnly = isJSDocImportTag(declaration) || (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly);
if (isTypeOnly) {
return grammarErrorOnNode(node, isImportAttributes ? Diagnostics.Import_attributes_cannot_be_used_with_type_only_imports_or_exports : Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports);
}
@@ -46957,6 +46970,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return checkJSDocSatisfiesTag(node as JSDocSatisfiesTag);
case SyntaxKind.JSDocThisTag:
return checkJSDocThisTag(node as JSDocThisTag);
case SyntaxKind.JSDocImportTag:
return checkJSDocImportTag(node as JSDocImportTag);
case SyntaxKind.IndexedAccessType:
return checkIndexedAccessType(node as IndexedAccessTypeNode);
case SyntaxKind.MappedType:
@@ -47913,6 +47928,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (
(isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent as ImportDeclaration).moduleSpecifier === node) ||
(isInJSFile(node) && isJSDocImportTag(node.parent) && node.parent.moduleSpecifier === node) ||
((isInJSFile(node) && isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false)) || isImportCall(node.parent)) ||
(isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent)
) {
+22
View File
@@ -243,6 +243,7 @@ import {
JSDocEnumTag,
JSDocFunctionType,
JSDocImplementsTag,
JSDocImportTag,
JSDocNameReference,
JSDocNonNullableType,
JSDocNullableType,
@@ -1826,6 +1827,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return emitJSDocTypedefTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocSeeTag:
return emitJSDocSeeTag(node as JSDocSeeTag);
case SyntaxKind.JSDocImportTag:
return emitJSDocImportTag(node as JSDocImportTag);
// SyntaxKind.JSDocPropertyTag (see JSDocParameterTag, above)
// Transformation nodes
@@ -4006,6 +4009,25 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
emitJSDocComment(tag.comment);
}
function emitJSDocImportTag(tag: JSDocImportTag) {
emitJSDocTagName(tag.tagName);
writeSpace();
if (tag.importClause) {
emit(tag.importClause);
writeSpace();
emitTokenWithComment(SyntaxKind.FromKeyword, tag.importClause.end, writeKeyword, tag);
writeSpace();
}
emitExpression(tag.moduleSpecifier);
if (tag.attributes) {
emitWithLeadingSpace(tag.attributes);
}
emitJSDocComment(tag.comment);
}
function emitJSDocNameReference(node: JSDocNameReference) {
writeSpace();
writePunctuation("{");
+25
View File
@@ -226,6 +226,7 @@ import {
JSDocEnumTag,
JSDocFunctionType,
JSDocImplementsTag,
JSDocImportTag,
JSDocLink,
JSDocLinkCode,
JSDocLinkPlain,
@@ -857,6 +858,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
updateJSDocImplementsTag,
createJSDocSeeTag,
updateJSDocSeeTag,
createJSDocImportTag,
updateJSDocImportTag,
createJSDocNameReference,
updateJSDocNameReference,
createJSDocMemberName,
@@ -5523,6 +5526,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
: node;
}
// @api
function createJSDocImportTag(tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes?: ImportAttributes, comment?: string | NodeArray<JSDocComment>): JSDocImportTag {
const node = createBaseJSDocTag<JSDocImportTag>(SyntaxKind.JSDocImportTag, tagName ?? createIdentifier("import"), comment);
node.importClause = importClause;
node.moduleSpecifier = moduleSpecifier;
node.attributes = attributes;
node.comment = comment;
return node;
}
function updateJSDocImportTag(node: JSDocImportTag, tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes: ImportAttributes | undefined, comment: string | NodeArray<JSDocComment> | undefined): JSDocImportTag {
return node.tagName !== tagName
|| node.comment !== comment
|| node.importClause !== importClause
|| node.moduleSpecifier !== moduleSpecifier
|| node.attributes !== attributes
? update(createJSDocImportTag(tagName, importClause, moduleSpecifier, attributes, comment), node)
: node;
}
// @api
function createJSDocText(text: string): JSDocText {
const node = createBaseNode<JSDocText>(SyntaxKind.JSDocText);
@@ -7179,6 +7202,8 @@ function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string {
return "augments";
case SyntaxKind.JSDocImplementsTag:
return "implements";
case SyntaxKind.JSDocImportTag:
return "import";
default:
return Debug.fail(`Unsupported kind: ${Debug.formatSyntaxKind(kind)}`);
}
+5
View File
@@ -91,6 +91,7 @@ import {
JSDocEnumTag,
JSDocFunctionType,
JSDocImplementsTag,
JSDocImportTag,
JSDocLink,
JSDocLinkCode,
JSDocLinkPlain,
@@ -1183,6 +1184,10 @@ export function isJSDocThrowsTag(node: Node): node is JSDocThrowsTag {
return node.kind === SyntaxKind.JSDocThrowsTag;
}
export function isJSDocImportTag(node: Node): node is JSDocImportTag {
return node.kind === SyntaxKind.JSDocImportTag;
}
// Synthesized list
/** @internal */
+53 -13
View File
@@ -175,6 +175,7 @@ import {
JSDocEnumTag,
JSDocFunctionType,
JSDocImplementsTag,
JSDocImportTag,
JSDocLink,
JSDocLinkCode,
JSDocLinkPlain,
@@ -1125,6 +1126,7 @@ const forEachChildTable: ForEachChildTable = {
[SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag,
[SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag,
[SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag,
[SyntaxKind.JSDocImportTag]: forEachChildInJSDocImportTag,
[SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression,
};
@@ -1214,6 +1216,14 @@ function forEachChildInJSDocTag<T>(node: JSDocUnknownTag | JSDocClassTag | JSDoc
|| (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
}
function forEachChildInJSDocImportTag<T>(node: JSDocImportTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
return visitNode(cbNode, node.tagName)
|| visitNode(cbNode, node.importClause)
|| visitNode(cbNode, node.moduleSpecifier)
|| visitNode(cbNode, node.attributes)
|| (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
}
function forEachChildInPartiallyEmittedExpression<T>(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
return visitNode(cbNode, node.expression);
}
@@ -3875,7 +3885,7 @@ namespace Parser {
}
function parseJSDocType(): TypeNode {
scanner.setInJSDocType(true);
scanner.setSkipJsDocLeadingAsterisks(true);
const pos = getNodePos();
if (parseOptional(SyntaxKind.ModuleKeyword)) {
// TODO(rbuckton): We never set the type for a JSDocNamepathType. What should we put here?
@@ -3893,13 +3903,13 @@ namespace Parser {
}
}
scanner.setInJSDocType(false);
scanner.setSkipJsDocLeadingAsterisks(false);
return finishNode(moduleTag, pos);
}
const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken);
let type = parseTypeOrTypePredicate();
scanner.setInJSDocType(false);
scanner.setSkipJsDocLeadingAsterisks(false);
if (hasDotDotDot) {
type = finishNode(factory.createJSDocVariadicType(type), pos);
}
@@ -8346,6 +8356,16 @@ namespace Parser {
return parseImportEqualsDeclaration(pos, hasJSDoc, modifiers, identifier, isTypeOnly);
}
const importClause = tryParseImportClause(identifier, afterImportPos, isTypeOnly);
const moduleSpecifier = parseModuleSpecifier();
const attributes = tryParseImportAttributes();
parseSemicolon();
const node = factory.createImportDeclaration(modifiers, importClause, moduleSpecifier, attributes);
return withJSDoc(finishNode(node, pos), hasJSDoc);
}
function tryParseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks = false) {
// ImportDeclaration:
// import ImportClause from ModuleSpecifier ;
// import ModuleSpecifier;
@@ -8355,18 +8375,17 @@ namespace Parser {
token() === SyntaxKind.AsteriskToken || // import *
token() === SyntaxKind.OpenBraceToken // import {
) {
importClause = parseImportClause(identifier, afterImportPos, isTypeOnly);
importClause = parseImportClause(identifier, pos, isTypeOnly, skipJsDocLeadingAsterisks);
parseExpected(SyntaxKind.FromKeyword);
}
const moduleSpecifier = parseModuleSpecifier();
return importClause;
}
function tryParseImportAttributes() {
const currentToken = token();
let attributes: ImportAttributes | undefined;
if ((currentToken === SyntaxKind.WithKeyword || currentToken === SyntaxKind.AssertKeyword) && !scanner.hasPrecedingLineBreak()) {
attributes = parseImportAttributes(currentToken);
return parseImportAttributes(currentToken);
}
parseSemicolon();
const node = factory.createImportDeclaration(modifiers, importClause, moduleSpecifier, attributes);
return withJSDoc(finishNode(node, pos), hasJSDoc);
}
function parseImportAttribute() {
@@ -8422,7 +8441,7 @@ namespace Parser {
return finished;
}
function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean) {
function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks: boolean) {
// ImportClause:
// ImportedDefaultBinding
// NameSpaceImport
@@ -8437,7 +8456,9 @@ namespace Parser {
!identifier ||
parseOptional(SyntaxKind.CommaToken)
) {
if (skipJsDocLeadingAsterisks) scanner.setSkipJsDocLeadingAsterisks(true);
namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
if (skipJsDocLeadingAsterisks) scanner.setSkipJsDocLeadingAsterisks(false);
}
return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos);
@@ -9073,6 +9094,9 @@ namespace Parser {
case "throws":
tag = parseThrowsTag(start, tagName, margin, indentText);
break;
case "import":
tag = parseImportTag(start, tagName, margin, indentText);
break;
default:
tag = parseUnknownTag(start, tagName, margin, indentText);
break;
@@ -9445,13 +9469,29 @@ namespace Parser {
return finishNode(factory.createJSDocSatisfiesTag(tagName, typeExpression, comments), start);
}
function parseImportTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImportTag {
const afterImportTagPos = scanner.getTokenFullStart();
let identifier: Identifier | undefined;
if (isIdentifier()) {
identifier = parseIdentifier();
}
const importClause = tryParseImportClause(identifier, afterImportTagPos, /*isTypeOnly*/ true, /*skipJsDocLeadingAsterisks*/ true);
const moduleSpecifier = parseModuleSpecifier();
const attributes = tryParseImportAttributes();
const comments = margin !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), margin, indentText) : undefined;
return finishNode(factory.createJSDocImportTag(tagName, importClause, moduleSpecifier, attributes, comments), start);
}
function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; } {
const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
const pos = getNodePos();
const expression = parsePropertyAccessEntityNameExpression();
scanner.setInJSDocType(true);
scanner.setSkipJsDocLeadingAsterisks(true);
const typeArguments = tryParseTypeArguments();
scanner.setInJSDocType(false);
scanner.setSkipJsDocLeadingAsterisks(false);
const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; };
const res = finishNode(node, pos);
if (usedBrace) {
+12 -3
View File
@@ -192,6 +192,7 @@ import {
isImportTypeNode,
isIncrementalCompilation,
isInJSFile,
isJSDocImportTag,
isLiteralImportTypeNode,
isModifier,
isModuleDeclaration,
@@ -205,6 +206,7 @@ import {
isStringLiteral,
isStringLiteralLike,
isTraceEnabled,
JSDocImportTag,
JsonSourceFile,
JsxEmit,
length,
@@ -868,7 +870,7 @@ export function getModeForResolutionAtIndex(file: SourceFileImportsList, index:
}
/** @internal */
export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | ExportDeclaration) {
export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | ExportDeclaration | JSDocImportTag) {
if (isExportDeclaration(decl)) {
return decl.isTypeOnly;
}
@@ -3346,7 +3348,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
collectDynamicImportOrRequireCalls(file);
collectDynamicImportOrRequireOrJsDocImportCalls(file);
}
file.imports = imports || emptyArray;
@@ -3403,7 +3405,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
}
function collectDynamicImportOrRequireCalls(file: SourceFile) {
function collectDynamicImportOrRequireOrJsDocImportCalls(file: SourceFile) {
const r = /import|require/g;
while (r.exec(file.text) !== null) { // eslint-disable-line no-null/no-null
const node = getNodeAtPosition(file, r.lastIndex);
@@ -3420,6 +3422,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here
imports = append(imports, node.argument.literal);
}
else if (isJavaScriptFile && isJSDocImportTag(node)) {
const moduleNameExpr = getExternalModuleName(node);
if (moduleNameExpr && isStringLiteral(moduleNameExpr) && moduleNameExpr.text) {
setParentRecursive(node, /*incremental*/ false);
imports = append(imports, moduleNameExpr);
}
}
}
}
+6 -6
View File
@@ -103,7 +103,7 @@ export interface Scanner {
setTextPos(textPos: number): void;
resetTokenState(pos: number): void;
/** @internal */
setInJSDocType(inType: boolean): void;
setSkipJsDocLeadingAsterisks(skip: boolean): void;
// Invokes the provided callback then unconditionally restores the scanner to the state it
// was in immediately prior to invoking the callback. The result of invoking the callback
// is returned from this function.
@@ -978,7 +978,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
var tokenFlags: TokenFlags;
var commentDirectives: CommentDirective[] | undefined;
var inJSDocType = 0;
var skipJsDocLeadingAsterisks = 0;
var scriptKind = ScriptKind.Unknown;
var jsDocParsingMode = JSDocParsingMode.ParseAll;
@@ -1032,7 +1032,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
setOnError,
resetTokenState,
setTextPos: resetTokenState,
setInJSDocType,
setSkipJsDocLeadingAsterisks,
tryScan,
lookAhead,
scanRange,
@@ -1892,7 +1892,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
return pos += 2, token = SyntaxKind.AsteriskAsteriskToken;
}
pos++;
if (inJSDocType && !asteriskSeen && (tokenFlags & TokenFlags.PrecedingLineBreak)) {
if (skipJsDocLeadingAsterisks && !asteriskSeen && (tokenFlags & TokenFlags.PrecedingLineBreak)) {
// decoration at the start of a JSDoc comment line
asteriskSeen = true;
continue;
@@ -2804,8 +2804,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
tokenFlags = TokenFlags.None;
}
function setInJSDocType(inType: boolean) {
inJSDocType += inType ? 1 : -1;
function setSkipJsDocLeadingAsterisks(skip: boolean) {
skipJsDocLeadingAsterisks += skip ? 1 : -1;
}
}
@@ -110,6 +110,7 @@ import {
isIndexSignatureDeclaration,
isInterfaceDeclaration,
isInternalDeclaration,
isJSDocImportTag,
isJsonSourceFile,
isLateVisibilityPaintedStatement,
isLiteralImportTypeNode,
@@ -1313,6 +1314,8 @@ export function transformDeclarations(context: TransformationContext) {
}
if (isDeclaration(input) && isDeclarationAndNotVisible(input)) return;
if (isJSDocImportTag(input)) return;
// Elide implementation signatures from overload sets
if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;
+22 -7
View File
@@ -439,6 +439,7 @@ export const enum SyntaxKind {
JSDocPropertyTag,
JSDocThrowsTag,
JSDocSatisfiesTag,
JSDocImportTag,
// Synthesized list
SyntaxList,
@@ -481,9 +482,9 @@ export const enum SyntaxKind {
LastStatement = DebuggerStatement,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocSatisfiesTag,
LastJSDocNode = JSDocImportTag,
FirstJSDocTagNode = JSDocTag,
LastJSDocTagNode = JSDocSatisfiesTag,
LastJSDocTagNode = JSDocImportTag,
/** @internal */ FirstContextualKeyword = AbstractKeyword,
/** @internal */ LastContextualKeyword = OfKeyword,
}
@@ -1036,7 +1037,8 @@ export type ForEachChildNodes =
| JSDocThrowsTag
| JSDocOverrideTag
| JSDocSatisfiesTag
| JSDocOverloadTag;
| JSDocOverloadTag
| JSDocImportTag;
/** @internal */
export type HasChildren =
@@ -3646,7 +3648,7 @@ export type NamedExportBindings =
// import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
export interface ImportClause extends NamedDeclaration {
readonly kind: SyntaxKind.ImportClause;
readonly parent: ImportDeclaration;
readonly parent: ImportDeclaration | JSDocImportTag;
readonly isTypeOnly: boolean;
readonly name?: Identifier; // Default binding
readonly namedBindings?: NamedImportBindings;
@@ -4058,6 +4060,14 @@ export interface JSDocSatisfiesExpression extends ParenthesizedExpression {
readonly _jsDocSatisfiesExpressionBrand: never;
}
export interface JSDocImportTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocImportTag;
readonly parent: JSDoc;
readonly importClause?: ImportClause;
readonly moduleSpecifier: Expression;
readonly attributes?: ImportAttributes;
}
// NOTE: Ensure this is up-to-date with src/debug/debug.ts
// dprint-ignore
export const enum FlowFlags {
@@ -5436,7 +5446,10 @@ export type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | Assert
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
/** @internal */
export type AnyImportOrRequire = AnyImportSyntax | VariableDeclarationInitializedTo<RequireOrImportCall>;
export type AnyImportOrJsDocImport = AnyImportSyntax | JSDocImportTag;
/** @internal */
export type AnyImportOrRequire = AnyImportOrJsDocImport | VariableDeclarationInitializedTo<RequireOrImportCall>;
/** @internal */
export type AnyImportOrBareOrAccessedRequire = AnyImportSyntax | VariableDeclarationInitializedTo<RequireOrImportCall | AccessExpression>;
@@ -5471,7 +5484,7 @@ export interface ValidImportTypeNode extends ImportTypeNode {
/** @internal */
export type AnyValidImportOrReExport =
| (ImportDeclaration | ExportDeclaration) & { moduleSpecifier: StringLiteral; }
| (ImportDeclaration | ExportDeclaration | JSDocImportTag) & { moduleSpecifier: StringLiteral; }
| ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteral; }; }
| RequireOrImportCall
| ValidImportTypeNode;
@@ -5496,7 +5509,7 @@ export interface RequireVariableDeclarationList extends VariableDeclarationList
/** @internal */
export type LateVisibilityPaintedStatement =
| AnyImportSyntax
| AnyImportOrJsDocImport
| VariableStatement
| ClassDeclaration
| FunctionDeclaration
@@ -8767,6 +8780,8 @@ export interface NodeFactory {
updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray<JSDocComment> | undefined): JSDocThrowsTag;
createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray<JSDocComment>): JSDocSatisfiesTag;
updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray<JSDocComment> | undefined): JSDocSatisfiesTag;
createJSDocImportTag(tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes?: ImportAttributes, comment?: string | NodeArray<JSDocComment>): JSDocImportTag;
updateJSDocImportTag(node: JSDocImportTag, tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes: ImportAttributes | undefined, comment: string | NodeArray<JSDocComment> | undefined): JSDocImportTag;
createJSDocText(text: string): JSDocText;
updateJSDocText(node: JSDocText, text: string): JSDocText;
createJSDocComment(comment?: string | NodeArray<JSDocComment> | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc;
+8 -4
View File
@@ -354,6 +354,7 @@ import {
JSDocArray,
JSDocCallbackTag,
JSDocEnumTag,
JSDocImportTag,
JSDocMemberName,
JSDocOverloadTag,
JSDocParameterTag,
@@ -3981,13 +3982,14 @@ export function isFunctionSymbol(symbol: Symbol | undefined) {
}
/** @internal */
export function tryGetModuleSpecifierFromDeclaration(node: AnyImportOrBareOrAccessedRequire | AliasDeclarationNode | ExportDeclaration | ImportTypeNode): StringLiteralLike | undefined {
export function tryGetModuleSpecifierFromDeclaration(node: AnyImportOrBareOrAccessedRequire | AliasDeclarationNode | ExportDeclaration | ImportTypeNode | JSDocImportTag): StringLiteralLike | undefined {
switch (node.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
return findAncestor(node.initializer, (node): node is RequireOrImportCall => isRequireCall(node, /*requireStringLiteralLikeArgument*/ true))?.arguments[0];
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.JSDocImportTag:
return tryCast(node.moduleSpecifier, isStringLiteralLike);
case SyntaxKind.ImportEqualsDeclaration:
return tryCast(tryCast(node.moduleReference, isExternalModuleReference)?.expression, isStringLiteralLike);
@@ -4016,6 +4018,7 @@ export function tryGetImportFromModuleSpecifier(node: StringLiteralLike): AnyVal
switch (node.parent.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.JSDocImportTag:
return node.parent as AnyValidImportOrReExport;
case SyntaxKind.ExternalModuleReference:
return (node.parent as ExternalModuleReference).parent as AnyValidImportOrReExport;
@@ -4030,10 +4033,11 @@ export function tryGetImportFromModuleSpecifier(node: StringLiteralLike): AnyVal
}
/** @internal */
export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall | ModuleDeclaration): Expression | undefined {
export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall | ModuleDeclaration | JSDocImportTag): Expression | undefined {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.JSDocImportTag:
return node.moduleSpecifier;
case SyntaxKind.ImportEqualsDeclaration:
return node.moduleReference.kind === SyntaxKind.ExternalModuleReference ? node.moduleReference.expression : undefined;
@@ -4063,8 +4067,8 @@ export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqua
}
/** @internal */
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name;
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration | JSDocImportTag): boolean {
return (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.JSDocImportTag) && !!node.importClause && !!node.importClause.name;
}
/** @internal */
@@ -37,8 +37,8 @@ registerCodeFix({
const declaration = getDeclaration(context.sourceFile, context.span.start);
if (declaration) {
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declaration));
const importDeclarationChanges = declaration.kind === SyntaxKind.ImportSpecifier && canConvertImportDeclarationForSpecifier(declaration, context.sourceFile, context.program)
? textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declaration.parent.parent.parent))
const importDeclarationChanges = declaration.kind === SyntaxKind.ImportSpecifier && isImportDeclaration(declaration.parent.parent.parent) && canConvertImportDeclarationForSpecifier(declaration, context.sourceFile, context.program)
? textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declaration.parent.parent.parent as ImportDeclaration))
: undefined;
const mainAction = createCodeFixAction(
fixId,
@@ -71,6 +71,7 @@ registerCodeFix({
}
else if (
errorDeclaration?.kind === SyntaxKind.ImportSpecifier
&& isImportDeclaration(errorDeclaration.parent.parent.parent)
&& !fixedImportDeclarations.has(errorDeclaration.parent.parent.parent)
&& canConvertImportDeclarationForSpecifier(errorDeclaration, diag.file, context.program)
) {
+11 -3
View File
@@ -72,6 +72,7 @@ import {
isImportEqualsDeclaration,
isInJSFile,
isIntrinsicJsxName,
isJSDocImportTag,
isJsxClosingElement,
isJsxOpeningFragment,
isJsxOpeningLikeElement,
@@ -694,6 +695,7 @@ function getNamespaceLikeImportText(declaration: AnyImportOrRequire) {
return tryCast(declaration.name, isIdentifier)?.text;
case SyntaxKind.ImportEqualsDeclaration:
return declaration.name.text;
case SyntaxKind.JSDocImportTag:
case SyntaxKind.ImportDeclaration:
return tryCast(declaration.importClause?.namedBindings, isNamespaceImport)?.name.text;
default:
@@ -806,7 +808,7 @@ function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile
(importMap ||= createMultiMap()).add(getSymbolId(moduleSymbol), i.parent);
}
}
else if (i.kind === SyntaxKind.ImportDeclaration || i.kind === SyntaxKind.ImportEqualsDeclaration) {
else if (i.kind === SyntaxKind.ImportDeclaration || i.kind === SyntaxKind.ImportEqualsDeclaration || i.kind === SyntaxKind.JSDocImportTag) {
const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
if (moduleSymbol) {
(importMap ||= createMultiMap()).add(getSymbolId(moduleSymbol), i);
@@ -816,10 +818,16 @@ function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile
return {
getImportsForExportInfo: ({ moduleSymbol, exportKind, targetFlags, symbol }: SymbolExportInfo): readonly FixAddToExistingImportInfo[] => {
// Can't use an es6 import for a type in JS.
if (!(targetFlags & SymbolFlags.Value) && isSourceFileJS(importingFile)) return emptyArray;
const matchingDeclarations = importMap?.get(getSymbolId(moduleSymbol));
if (!matchingDeclarations) return emptyArray;
// Can't use an es6 import for a type in JS.
if (
isSourceFileJS(importingFile)
&& !(targetFlags & SymbolFlags.Value)
&& !every(matchingDeclarations, isJSDocImportTag)
) return emptyArray;
const importKind = getImportKind(importingFile, exportKind, compilerOptions);
return matchingDeclarations.map(declaration => ({ declaration, importKind, symbol, targetFlags }));
},
+2 -1
View File
@@ -7,6 +7,7 @@ import {
Identifier,
isExternalModuleReference,
isIdentifier,
isImportDeclaration,
isImportEqualsDeclaration,
isNamespaceImport,
makeImport,
@@ -51,7 +52,7 @@ function getInfo(sourceFile: SourceFile, pos: number): Info | undefined {
if (isImportEqualsDeclaration(parent) && isExternalModuleReference(parent.moduleReference)) {
return { importNode: parent, name, moduleSpecifier: parent.moduleReference.expression };
}
else if (isNamespaceImport(parent)) {
else if (isNamespaceImport(parent) && isImportDeclaration(parent.parent.parent)) {
const importNode = parent.parent.parent;
return { importNode, name, moduleSpecifier: importNode.moduleSpecifier };
}
+28 -19
View File
@@ -188,6 +188,7 @@ import {
isJSDoc,
isJSDocAugmentsTag,
isJSDocImplementsTag,
isJSDocImportTag,
isJSDocParameterTag,
isJSDocTag,
isJSDocTemplateTag,
@@ -255,6 +256,7 @@ import {
isVariableDeclaration,
isVariableLike,
JsDoc,
JSDocImportTag,
JSDocParameterTag,
JSDocPropertyTag,
JSDocReturnTag,
@@ -3202,6 +3204,7 @@ function getCompletionData(
log("getCompletionData: Is inside comment: " + (timestamp() - start));
let insideJsDocTagTypeExpression = false;
let insideJsDocImportTag = false;
let isInSnippetScope = false;
if (insideComment) {
if (hasDocComment(sourceFile, position)) {
@@ -3242,25 +3245,30 @@ function getCompletionData(
if (tag.tagName.pos <= position && position <= tag.tagName.end) {
return { kind: CompletionDataKind.JsDocTagName };
}
const typeExpression = tryGetTypeExpressionFromTag(tag);
if (typeExpression) {
currentToken = getTokenAtPosition(sourceFile, position);
if (
!currentToken ||
(!isDeclarationName(currentToken) &&
(currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag ||
(currentToken.parent as JSDocPropertyTag).name !== currentToken))
) {
// Use as type location if inside tag's type expression
insideJsDocTagTypeExpression = isCurrentlyEditingNode(typeExpression);
}
if (isJSDocImportTag(tag)) {
insideJsDocImportTag = true;
}
if (!insideJsDocTagTypeExpression && isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
return { kind: CompletionDataKind.JsDocParameterName, tag };
else {
const typeExpression = tryGetTypeExpressionFromTag(tag);
if (typeExpression) {
currentToken = getTokenAtPosition(sourceFile, position);
if (
!currentToken ||
(!isDeclarationName(currentToken) &&
(currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag ||
(currentToken.parent as JSDocPropertyTag).name !== currentToken))
) {
// Use as type location if inside tag's type expression
insideJsDocTagTypeExpression = isCurrentlyEditingNode(typeExpression);
}
}
if (!insideJsDocTagTypeExpression && isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
return { kind: CompletionDataKind.JsDocParameterName, tag };
}
}
}
if (!insideJsDocTagTypeExpression) {
if (!insideJsDocTagTypeExpression && !insideJsDocImportTag) {
// Proceed if the current position is in jsDoc tag expression; otherwise it is a normal
// comment or the plain text part of a jsDoc comment, so no completion should be available
log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment.");
@@ -3271,7 +3279,7 @@ function getCompletionData(
start = timestamp();
// The decision to provide completion depends on the contextToken, which is determined through the previousToken.
// Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
const isJsOnlyLocation = !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile);
const isJsOnlyLocation = !insideJsDocTagTypeExpression && !insideJsDocImportTag && isSourceFileJS(sourceFile);
const tokens = getRelevantTokens(position, sourceFile);
const previousToken = tokens.previousToken!;
let contextToken = tokens.contextToken!;
@@ -3952,6 +3960,7 @@ function getCompletionData(
function isTypeOnlyCompletion(): boolean {
return insideJsDocTagTypeExpression
|| insideJsDocImportTag
|| !!importStatementCompletion && isTypeOnlyImportOrExportDeclaration(location.parent)
|| !isContextTokenValueLocation(contextToken) &&
(isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker)
@@ -5742,9 +5751,9 @@ function getImportStatementCompletionInfo(contextToken: Node, sourceFile: Source
}
}
function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclaration | ImportEqualsDeclaration | ImportSpecifier | Token<SyntaxKind.ImportKeyword> | undefined) {
function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclaration | ImportEqualsDeclaration | ImportSpecifier | JSDocImportTag | Token<SyntaxKind.ImportKeyword> | undefined) {
if (!node) return undefined;
const top = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration)) ?? node;
const top = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration, isJSDocImportTag)) ?? node;
const sourceFile = top.getSourceFile();
if (rangeIsOnSingleLine(top, sourceFile)) {
return createTextSpanFromNode(top, sourceFile);
@@ -5753,7 +5762,7 @@ function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclara
Debug.assert(top.kind !== SyntaxKind.ImportKeyword && top.kind !== SyntaxKind.ImportSpecifier);
// Guess which point in the import might actually be a later statement parsed as part of the import
// during parser recovery - either in the middle of named imports, or the module specifier.
const potentialSplitPoint = top.kind === SyntaxKind.ImportDeclaration
const potentialSplitPoint = top.kind === SyntaxKind.ImportDeclaration || top.kind === SyntaxKind.JSDocImportTag
? getPotentiallyInvalidImportSpecifier(top.importClause?.namedBindings) ?? top.moduleSpecifier
: top.moduleReference;
const withoutModuleSpecifier: TextRange = {
+5 -2
View File
@@ -1,5 +1,6 @@
import {
__String,
AnyImportOrJsDocImport,
AnyImportOrReExport,
AssignmentDeclarationKind,
BinaryExpression,
@@ -57,6 +58,7 @@ import {
isVariableDeclaration,
isVariableDeclarationInitializedToBareOrAccessedRequire,
isVariableStatement,
JSDocImportTag,
ModifierFlags,
ModuleBlock,
ModuleDeclaration,
@@ -138,7 +140,7 @@ interface AmbientModuleDeclaration extends ModuleDeclaration {
}
type SourceFileLike = SourceFile | AmbientModuleDeclaration;
// Identifier for the case of `const x = require("y")`.
type Importer = AnyImportOrReExport | ValidImportTypeNode | Identifier;
type Importer = AnyImportOrReExport | ValidImportTypeNode | Identifier | JSDocImportTag;
type ImporterOrCallExpression = Importer | CallExpression;
/** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */
@@ -215,6 +217,7 @@ function getImportersForExport(
break;
case SyntaxKind.ImportDeclaration:
case SyntaxKind.JSDocImportTag:
directImports.push(direct);
const namedBindings = direct.importClause && direct.importClause.namedBindings;
if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) {
@@ -267,7 +270,7 @@ function getImportersForExport(
});
}
function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void {
function handleNamespaceImport(importDeclaration: AnyImportOrJsDocImport, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void {
if (exportKind === ExportKind.ExportEquals) {
// This is a direct import, not import-as-namespace.
if (!alreadyAddedDirect) directImports.push(importDeclaration);
+1
View File
@@ -131,6 +131,7 @@ const jsDocTagNames = [
"host",
"ignore",
"implements",
"import",
"inheritdoc",
"inner",
"instance",
+3 -2
View File
@@ -40,6 +40,7 @@ import {
isString,
isStringLiteral,
isStringLiteralLike,
JSDocImportTag,
jsxModeNeedsExplicitImport,
LanguageServiceHost,
length,
@@ -709,7 +710,7 @@ function detectModuleSpecifierCaseBySort(importDeclsByGroup: (readonly AnyImport
return detectCaseSensitivityBySort(moduleSpecifiersByGroup, comparersToTest);
}
function detectNamedImportOrganizationBySort(originalGroups: readonly ImportDeclaration[], comparersToTest: Comparer<string>[], typesToTest: OrganizeImportsTypeOrder[]): { namedImportComparer: Comparer<string>; typeOrder: OrganizeImportsTypeOrder | undefined; isSorted: boolean; } | undefined {
function detectNamedImportOrganizationBySort(originalGroups: readonly (ImportDeclaration | JSDocImportTag)[], comparersToTest: Comparer<string>[], typesToTest: OrganizeImportsTypeOrder[]): { namedImportComparer: Comparer<string>; typeOrder: OrganizeImportsTypeOrder | undefined; isSorted: boolean; } | undefined {
// Filter for import declarations with named imports. Will be a flat array of import declarations without separations by group
let bothNamedImports = false;
const importDeclsWithNamed = originalGroups.filter(i => {
@@ -884,7 +885,7 @@ function getNamedImportSpecifierComparer<T extends ImportOrExportSpecifier>(pref
}
/** @internal */
export function getNamedImportSpecifierComparerWithDetection(importDecl: ImportDeclaration, preferences: UserPreferences, sourceFile?: SourceFile): { specifierComparer: Comparer<ImportSpecifier>; isSorted: boolean | undefined; } {
export function getNamedImportSpecifierComparerWithDetection(importDecl: ImportDeclaration | JSDocImportTag, preferences: UserPreferences, sourceFile?: SourceFile): { specifierComparer: Comparer<ImportSpecifier>; isSorted: boolean | undefined; } {
// sort case sensitivity:
// - if the user preference is explicit, use that
// - otherwise, if there are enough existing import specifiers in this import to detect unambiguously, use that
+17 -9
View File
@@ -24,12 +24,14 @@ import {
ImportSpecifier,
isExportSpecifier,
isImportDeclaration,
isJSDocImportTag,
isPropertyAccessExpression,
isPropertyAccessOrQualifiedName,
isShorthandPropertyAssignment,
isStringLiteral,
NamedImports,
NamespaceImport,
or,
Program,
PropertyAccessExpression,
QualifiedName,
@@ -110,8 +112,8 @@ function getImportConversionInfo(context: RefactorContext, considerPartialSpans
const { file } = context;
const span = getRefactorContextSpan(context);
const token = getTokenAtPosition(file, span.start);
const importDecl = considerPartialSpans ? findAncestor(token, isImportDeclaration) : getParentNodeInSpan(token, file, span);
if (!importDecl || !isImportDeclaration(importDecl)) return { error: "Selection is not an import declaration." };
const importDecl = considerPartialSpans ? findAncestor(token, or(isImportDeclaration, isJSDocImportTag)) : getParentNodeInSpan(token, file, span);
if (importDecl === undefined || !(isImportDeclaration(importDecl) || isJSDocImportTag(importDecl))) return { error: "Selection is not an import declaration." };
const end = span.start + span.length;
const nextToken = findNextToken(importDecl, importDecl.parent, file);
@@ -189,12 +191,13 @@ function doChangeNamespaceToNamed(sourceFile: SourceFile, checker: TypeChecker,
});
const importDecl = toConvert.parent.parent;
if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports) {
if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports && isImportDeclaration(importDecl)) {
// Need to leave the namespace import alone
changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers));
changes.insertNodeAfter(sourceFile, importDecl, createImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers));
}
else {
changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers));
const defaultImportName = usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined;
changes.replaceNode(sourceFile, toConvert.parent, createImportClause(defaultImportName, importSpecifiers));
}
}
@@ -266,9 +269,10 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra
? factory.createIdentifier(namespaceImportName)
: factory.createNamespaceImport(factory.createIdentifier(namespaceImportName)),
);
if (neededNamedImports.size) {
if (neededNamedImports.size && isImportDeclaration(importDecl)) {
const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values(), element => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text)));
changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports));
changes.insertNodeAfter(sourceFile, toConvert.parent.parent, createImport(importDecl, /*defaultImportName*/ undefined, newNamedImports));
}
}
@@ -279,6 +283,10 @@ function isExportEqualsModule(moduleSpecifier: Expression, checker: TypeChecker)
return externalModule !== exportEquals;
}
function updateImport(old: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration {
return factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*attributes*/ undefined);
function createImport(node: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration {
return factory.createImportDeclaration(/*modifiers*/ undefined, createImportClause(defaultImportName, elements), node.moduleSpecifier, /*attributes*/ undefined);
}
function createImportClause(defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined) {
return factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined);
}
+1
View File
@@ -420,6 +420,7 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExternalModuleReference:
case SyntaxKind.JSDocImportTag:
// Get all known external module names or complete a path to a module
// i.e. import * as ns from "/*completion position*/";
// var y = import("/*completion position*/");
+4 -1
View File
@@ -188,6 +188,7 @@ import {
isInternalModuleImportEqualsDeclaration,
isJSDoc,
isJSDocCommentContainingNode,
isJSDocImportTag,
isJSDocLink,
isJSDocLinkCode,
isJSDocLinkLike,
@@ -258,6 +259,7 @@ import {
isWhiteSpaceSingleLine,
isYieldExpression,
IterationStatement,
JSDocImportTag,
JSDocLink,
JSDocLinkCode,
JSDocLinkDisplayPart,
@@ -1244,7 +1246,7 @@ function getAdjustedLocationForDeclaration(node: Node, forRename: boolean) {
}
}
function getAdjustedLocationForImportDeclaration(node: ImportDeclaration, forRename: boolean) {
function getAdjustedLocationForImportDeclaration(node: ImportDeclaration | JSDocImportTag, forRename: boolean) {
if (node.importClause) {
if (node.importClause.name && node.importClause.namedBindings) {
// do not adjust if we have both a name and named bindings
@@ -2578,6 +2580,7 @@ export function isModuleSpecifierLike(node: Node): node is StringLiteralLike {
return isStringLiteralLike(node) && (
isExternalModuleReference(node.parent) ||
isImportDeclaration(node.parent) ||
isJSDocImportTag(node.parent) ||
isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) && node.parent.arguments[0] === node ||
isImportCall(node.parent) && node.parent.arguments[0] === node
);
+28
View File
@@ -204,6 +204,34 @@ describe("unittests:: JSDocParsing", () => {
*/`,
);
parsesCorrectly(
"importTag1",
`/**
* @import foo from 'foo'
*/`,
);
parsesCorrectly(
"importTag2",
`/**
* @import { foo } from 'foo'
*/`,
);
parsesCorrectly(
"importTag3",
`/**
* @import * as types from 'foo'
*/`,
);
parsesCorrectly(
"importTag4",
`/**
* @import * as types from 'foo' comment part
*/`,
);
parsesCorrectly(
"returnTag1",
`/**
@@ -0,0 +1,54 @@
{
"kind": "JSDoc",
"pos": 0,
"end": 35,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"tags": {
"0": {
"kind": "JSDocImportTag",
"pos": 8,
"end": 30,
"modifierFlagsCache": 0,
"transformFlags": 0,
"tagName": {
"kind": "Identifier",
"pos": 9,
"end": 15,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "import"
},
"importClause": {
"kind": "ImportClause",
"pos": 16,
"end": 19,
"modifierFlagsCache": 0,
"transformFlags": 1,
"isTypeOnly": true,
"name": {
"kind": "Identifier",
"pos": 16,
"end": 19,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "foo"
}
},
"moduleSpecifier": {
"kind": "StringLiteral",
"pos": 24,
"end": 30,
"modifierFlagsCache": 0,
"transformFlags": 0,
"text": "foo"
}
},
"length": 1,
"pos": 8,
"end": 30,
"hasTrailingComma": false,
"transformFlags": 0
}
}
@@ -0,0 +1,76 @@
{
"kind": "JSDoc",
"pos": 0,
"end": 39,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"tags": {
"0": {
"kind": "JSDocImportTag",
"pos": 8,
"end": 34,
"modifierFlagsCache": 0,
"transformFlags": 0,
"tagName": {
"kind": "Identifier",
"pos": 9,
"end": 15,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "import"
},
"importClause": {
"kind": "ImportClause",
"pos": 16,
"end": 23,
"modifierFlagsCache": 0,
"transformFlags": 1,
"isTypeOnly": true,
"namedBindings": {
"kind": "NamedImports",
"pos": 16,
"end": 23,
"modifierFlagsCache": 0,
"transformFlags": 0,
"elements": {
"0": {
"kind": "ImportSpecifier",
"pos": 17,
"end": 21,
"modifierFlagsCache": 0,
"transformFlags": 0,
"isTypeOnly": false,
"name": {
"kind": "Identifier",
"pos": 17,
"end": 21,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "foo"
}
},
"length": 1,
"pos": 17,
"end": 21,
"hasTrailingComma": false,
"transformFlags": 0
}
}
},
"moduleSpecifier": {
"kind": "StringLiteral",
"pos": 28,
"end": 34,
"modifierFlagsCache": 0,
"transformFlags": 0,
"text": "foo"
}
},
"length": 1,
"pos": 8,
"end": 34,
"hasTrailingComma": false,
"transformFlags": 0
}
}
@@ -0,0 +1,61 @@
{
"kind": "JSDoc",
"pos": 0,
"end": 42,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"tags": {
"0": {
"kind": "JSDocImportTag",
"pos": 8,
"end": 37,
"modifierFlagsCache": 0,
"transformFlags": 0,
"tagName": {
"kind": "Identifier",
"pos": 9,
"end": 15,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "import"
},
"importClause": {
"kind": "ImportClause",
"pos": 16,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 1,
"isTypeOnly": true,
"namedBindings": {
"kind": "NamespaceImport",
"pos": 16,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 0,
"name": {
"kind": "Identifier",
"pos": 20,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "types"
}
}
},
"moduleSpecifier": {
"kind": "StringLiteral",
"pos": 31,
"end": 37,
"modifierFlagsCache": 0,
"transformFlags": 0,
"text": "foo"
}
},
"length": 1,
"pos": 8,
"end": 37,
"hasTrailingComma": false,
"transformFlags": 0
}
}
@@ -0,0 +1,62 @@
{
"kind": "JSDoc",
"pos": 0,
"end": 55,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"tags": {
"0": {
"kind": "JSDocImportTag",
"pos": 8,
"end": 53,
"modifierFlagsCache": 0,
"transformFlags": 0,
"tagName": {
"kind": "Identifier",
"pos": 9,
"end": 15,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "import"
},
"comment": "comment part",
"importClause": {
"kind": "ImportClause",
"pos": 16,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 1,
"isTypeOnly": true,
"namedBindings": {
"kind": "NamespaceImport",
"pos": 16,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 0,
"name": {
"kind": "Identifier",
"pos": 20,
"end": 26,
"modifierFlagsCache": 0,
"transformFlags": 0,
"escapedText": "types"
}
}
},
"moduleSpecifier": {
"kind": "StringLiteral",
"pos": 31,
"end": 37,
"modifierFlagsCache": 0,
"transformFlags": 0,
"text": "foo"
}
},
"length": 1,
"pos": 8,
"end": 53,
"hasTrailingComma": false,
"transformFlags": 0
}
}
+20 -9
View File
@@ -3940,12 +3940,13 @@ declare namespace ts {
JSDocPropertyTag = 348,
JSDocThrowsTag = 349,
JSDocSatisfiesTag = 350,
SyntaxList = 351,
NotEmittedStatement = 352,
PartiallyEmittedExpression = 353,
CommaListExpression = 354,
SyntheticReferenceExpression = 355,
Count = 356,
JSDocImportTag = 351,
SyntaxList = 352,
NotEmittedStatement = 353,
PartiallyEmittedExpression = 354,
CommaListExpression = 355,
SyntheticReferenceExpression = 356,
Count = 357,
FirstAssignment = 64,
LastAssignment = 79,
FirstCompoundAssignment = 65,
@@ -3974,9 +3975,9 @@ declare namespace ts {
LastStatement = 259,
FirstNode = 166,
FirstJSDocNode = 309,
LastJSDocNode = 350,
LastJSDocNode = 351,
FirstJSDocTagNode = 327,
LastJSDocTagNode = 350,
LastJSDocTagNode = 351,
}
type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia;
type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral;
@@ -5426,7 +5427,7 @@ declare namespace ts {
type NamedExportBindings = NamespaceExport | NamedExports;
interface ImportClause extends NamedDeclaration {
readonly kind: SyntaxKind.ImportClause;
readonly parent: ImportDeclaration;
readonly parent: ImportDeclaration | JSDocImportTag;
readonly isTypeOnly: boolean;
readonly name?: Identifier;
readonly namedBindings?: NamedImportBindings;
@@ -5783,6 +5784,13 @@ declare namespace ts {
readonly kind: SyntaxKind.JSDocSatisfiesTag;
readonly typeExpression: JSDocTypeExpression;
}
interface JSDocImportTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocImportTag;
readonly parent: JSDoc;
readonly importClause?: ImportClause;
readonly moduleSpecifier: Expression;
readonly attributes?: ImportAttributes;
}
enum FlowFlags {
Unreachable = 1,
Start = 2,
@@ -7696,6 +7704,8 @@ declare namespace ts {
updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray<JSDocComment> | undefined): JSDocThrowsTag;
createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray<JSDocComment>): JSDocSatisfiesTag;
updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray<JSDocComment> | undefined): JSDocSatisfiesTag;
createJSDocImportTag(tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes?: ImportAttributes, comment?: string | NodeArray<JSDocComment>): JSDocImportTag;
updateJSDocImportTag(node: JSDocImportTag, tagName: Identifier | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, attributes: ImportAttributes | undefined, comment: string | NodeArray<JSDocComment> | undefined): JSDocImportTag;
createJSDocText(text: string): JSDocText;
updateJSDocText(node: JSDocText, text: string): JSDocText;
createJSDocComment(comment?: string | NodeArray<JSDocComment> | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc;
@@ -8998,6 +9008,7 @@ declare namespace ts {
function isJSDocImplementsTag(node: Node): node is JSDocImplementsTag;
function isJSDocSatisfiesTag(node: Node): node is JSDocSatisfiesTag;
function isJSDocThrowsTag(node: Node): node is JSDocThrowsTag;
function isJSDocImportTag(node: Node): node is JSDocImportTag;
function isQuestionOrExclamationToken(node: Node): node is QuestionToken | ExclamationToken;
function isIdentifierOrThisTypeNode(node: Node): node is Identifier | ThisTypeNode;
function isReadonlyKeywordOrPlusOrMinusToken(node: Node): node is ReadonlyKeyword | PlusToken | MinusToken;
@@ -0,0 +1,105 @@
// === findAllReferences ===
// === /a.js ===
// /**
// * <|@import { [|{| defId: 0, isWriteAccess: true |}A|] } from "./b";
// |>*/
//
// /**
// * @param { [|{| defId: 0 |}A|]/*FIND ALL REFS*/ } a
// */
// function f(a) {}
// === /b.ts ===
// <|export interface [|{| defId: 1, isWriteAccess: true |}A|] { }|>
// === Definitions ===
// === /a.js ===
// /**
// * <|@import { [|{| defId: 0 |}A|] } from "./b";
// |>*/
//
// /**
// * @param { A/*FIND ALL REFS*/ } a
// */
// function f(a) {}
// === /b.ts ===
// <|export interface [|{| defId: 1 |}A|] { }|>
// === Details ===
[
{
"defId": 0,
"containerKind": "",
"containerName": "",
"kind": "alias",
"name": "(alias) interface A\nimport A",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "alias",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "interface",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "A",
"kind": "aliasName"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": "import",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "A",
"kind": "aliasName"
}
]
},
{
"defId": 1,
"containerKind": "",
"containerName": "",
"kind": "interface",
"name": "interface A",
"displayParts": [
{
"text": "interface",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "A",
"kind": "interfaceName"
}
]
}
]
@@ -0,0 +1,17 @@
// === goToDefinition ===
// === /b.ts ===
// [||]export interface A { }
// === /a.js ===
// /**
// * @import { A } from [|"./b/*GOTO DEF*/"|]
// */
// === Details ===
[
{
"kind": "script",
"name": "./b",
"unverified": false
}
]
@@ -0,0 +1,5 @@
// === goToDefinition ===
// === /a.js ===
// /**
// * @import { A } from/*GOTO DEF*/ "./b"
// */
@@ -0,0 +1,5 @@
// === goToDefinition ===
// === /a.js ===
// /**
// * @import { A } from /*GOTO DEF*/ "./b";
// */
@@ -0,0 +1,20 @@
// === goToDefinition ===
// === /b.ts ===
// <|export interface [|A|] { }|>
// === /a.js ===
// /**
// * @import { [|A|]/*GOTO DEF*/ } from "./b";
// */
// === Details ===
[
{
"kind": "interface",
"name": "A",
"containerName": "\"/b\"",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]
@@ -0,0 +1,25 @@
// === goToDefinition ===
// === /b.ts ===
// <|export interface [|A|] { }|>
// === /a.js ===
// /**
// * @import { A } from "./b";
// */
//
// /**
// * @param { [|A|]/*GOTO DEF*/ } a
// */
// function f(a) {}
// === Details ===
[
{
"kind": "interface",
"name": "A",
"containerName": "\"/b\"",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/jsdoc/importTag1.ts] ////
=== /types.ts ===
export interface Foo {
>Foo : Symbol(Foo, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(Foo.a, Decl(types.ts, 0, 22))
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>foo : Symbol(foo, Decl(foo.js, 7, 11))
@@ -0,0 +1,20 @@
//// [tests/cases/conformance/jsdoc/importTag1.ts] ////
=== /types.ts ===
export interface Foo {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : (foo: Foo) => void
>foo : Foo
@@ -0,0 +1,11 @@
/foo.js(2,11): error TS1109: Expression expected.
==== /foo.js (1 errors) ====
/**
* @import
*/
!!! error TS1109: Expression expected.
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag10.ts] ////
=== /foo.js ===
/**
* @import
*/
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag10.ts] ////
=== /foo.js ===
/**
* @import
*/
@@ -0,0 +1,13 @@
/foo.js(2,15): error TS1109: Expression expected.
/foo.js(3,2): error TS1005: 'from' expected.
==== /foo.js (2 errors) ====
/**
* @import foo
!!! error TS1109: Expression expected.
*/
!!! error TS1005: 'from' expected.
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag11.ts] ////
=== /foo.js ===
/**
* @import foo
*/
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag11.ts] ////
=== /foo.js ===
/**
* @import foo
*/
@@ -0,0 +1,10 @@
/foo.js(2,20): error TS1109: Expression expected.
==== /foo.js (1 errors) ====
/**
* @import foo from
!!! error TS1109: Expression expected.
*/
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag12.ts] ////
=== /foo.js ===
/**
* @import foo from
*/
@@ -0,0 +1,8 @@
//// [tests/cases/conformance/jsdoc/importTag12.ts] ////
=== /foo.js ===
/**
* @import foo from
*/
@@ -0,0 +1,13 @@
/foo.js(1,15): error TS1005: 'from' expected.
==== /foo.js (1 errors) ====
/** @import x = require("types") */
~
!!! error TS1005: 'from' expected.
==== /types.ts (0 errors) ====
export interface Foo {
a: number;
}
@@ -0,0 +1,6 @@
//// [tests/cases/conformance/jsdoc/importTag13.ts] ////
=== /foo.js ===
/** @import x = require("types") */
@@ -0,0 +1,6 @@
//// [tests/cases/conformance/jsdoc/importTag13.ts] ////
=== /foo.js ===
/** @import x = require("types") */
@@ -0,0 +1,14 @@
/foo.js(1,33): error TS1464: Type import attributes should have exactly one key - 'resolution-mode' - with value 'import' or 'require'.
/foo.js(1,33): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
/foo.js(1,38): error TS1005: '{' expected.
==== /foo.js (3 errors) ====
/** @import * as f from "./foo" with */
~~~~
!!! error TS1464: Type import attributes should have exactly one key - 'resolution-mode' - with value 'import' or 'require'.
~~~~
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
!!! error TS1005: '{' expected.
@@ -0,0 +1,6 @@
//// [tests/cases/conformance/jsdoc/importTag14.ts] ////
=== /foo.js ===
/** @import * as f from "./foo" with */
@@ -0,0 +1,6 @@
//// [tests/cases/conformance/jsdoc/importTag14.ts] ////
=== /foo.js ===
/** @import * as f from "./foo" with */
@@ -0,0 +1,18 @@
1.js(1,30): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
1.js(2,33): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
==== 0.ts (0 errors) ====
export interface I { }
==== 1.js (2 errors) ====
/** @import { I } from './0' with { type: "json" } */
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
/** @import * as foo from './0' with { type: "json" } */
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
/** @param {I} a */
function f(a) {}
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
//// [0.ts]
export interface I { }
//// [1.js]
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
//// [0.d.ts]
export interface I {
}
//// [1.d.ts]
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
declare function f(a: I): void;
import type { I } from './0' with { type: "json" };
import type * as foo from './0';
@@ -0,0 +1,15 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
=== 0.ts ===
export interface I { }
>I : Symbol(I, Decl(0.ts, 0, 0))
=== 1.js ===
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
>f : Symbol(f, Decl(1.js, 0, 0))
>a : Symbol(a, Decl(1.js, 4, 11))
@@ -0,0 +1,15 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
=== 0.ts ===
export interface I { }
=== 1.js ===
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
>f : (a: I) => void
>a : I
@@ -0,0 +1,18 @@
1.js(1,30): error TS2857: Import attributes cannot be used with type-only imports or exports.
1.js(2,33): error TS2857: Import attributes cannot be used with type-only imports or exports.
==== 0.ts (0 errors) ====
export interface I { }
==== 1.js (2 errors) ====
/** @import { I } from './0' with { type: "json" } */
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2857: Import attributes cannot be used with type-only imports or exports.
/** @import * as foo from './0' with { type: "json" } */
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2857: Import attributes cannot be used with type-only imports or exports.
/** @param {I} a */
function f(a) {}
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
//// [0.ts]
export interface I { }
//// [1.js]
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
//// [0.d.ts]
export interface I {
}
//// [1.d.ts]
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
declare function f(a: I): void;
import type { I } from './0' with { type: "json" };
import type * as foo from './0';
@@ -0,0 +1,15 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
=== 0.ts ===
export interface I { }
>I : Symbol(I, Decl(0.ts, 0, 0))
=== 1.js ===
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
>f : Symbol(f, Decl(1.js, 0, 0))
>a : Symbol(a, Decl(1.js, 4, 11))
@@ -0,0 +1,15 @@
//// [tests/cases/conformance/jsdoc/importTag15.ts] ////
=== 0.ts ===
export interface I { }
=== 1.js ===
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
>f : (a: I) => void
>a : I
+32
View File
@@ -0,0 +1,32 @@
//// [tests/cases/conformance/jsdoc/importTag16.ts] ////
//// [a.ts]
export default interface Foo {}
export interface I {}
//// [b.js]
/** @import Foo, { I } from "./a" */
/**
* @param {Foo} a
* @param {I} b
*/
export function foo(a, b) {}
//// [a.d.ts]
export default interface Foo {
}
export interface I {
}
//// [b.d.ts]
/** @import Foo, { I } from "./a" */
/**
* @param {Foo} a
* @param {I} b
*/
export function foo(a: Foo, b: I): void;
import type Foo from "./a";
import type { I } from "./a";
@@ -0,0 +1,21 @@
//// [tests/cases/conformance/jsdoc/importTag16.ts] ////
=== a.ts ===
export default interface Foo {}
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
export interface I {}
>I : Symbol(I, Decl(a.ts, 0, 31))
=== b.js ===
/** @import Foo, { I } from "./a" */
/**
* @param {Foo} a
* @param {I} b
*/
export function foo(a, b) {}
>foo : Symbol(foo, Decl(b.js, 0, 0))
>a : Symbol(a, Decl(b.js, 6, 20))
>b : Symbol(b, Decl(b.js, 6, 22))
@@ -0,0 +1,19 @@
//// [tests/cases/conformance/jsdoc/importTag16.ts] ////
=== a.ts ===
export default interface Foo {}
export interface I {}
=== b.js ===
/** @import Foo, { I } from "./a" */
/**
* @param {Foo} a
* @param {I} b
*/
export function foo(a, b) {}
>foo : (a: Foo, b: I) => void
>a : Foo
>b : I
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/jsdoc/importTag2.ts] ////
=== /types.ts ===
export interface Foo {
>Foo : Symbol(Foo, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(Foo.a, Decl(types.ts, 0, 22))
}
=== /foo.js ===
/**
* @import * as types from "./types"
*/
/**
* @param { types.Foo } foo
*/
export function f(foo) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>foo : Symbol(foo, Decl(foo.js, 7, 18))
@@ -0,0 +1,20 @@
//// [tests/cases/conformance/jsdoc/importTag2.ts] ////
=== /types.ts ===
export interface Foo {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import * as types from "./types"
*/
/**
* @param { types.Foo } foo
*/
export function f(foo) {}
>f : (foo: types.Foo) => void
>foo : types.Foo
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/jsdoc/importTag3.ts] ////
=== /types.ts ===
export default interface Foo {
>Foo : Symbol(Foo, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(Foo.a, Decl(types.ts, 0, 30))
}
=== /foo.js ===
/**
* @import Foo from "./types"
*/
/**
* @param { Foo } foo
*/
export function f(foo) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>foo : Symbol(foo, Decl(foo.js, 7, 18))
@@ -0,0 +1,20 @@
//// [tests/cases/conformance/jsdoc/importTag3.ts] ////
=== /types.ts ===
export default interface Foo {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import Foo from "./types"
*/
/**
* @param { Foo } foo
*/
export function f(foo) {}
>f : (foo: Foo) => void
>foo : Foo
@@ -0,0 +1,27 @@
/foo.js(2,14): error TS2300: Duplicate identifier 'Foo'.
/foo.js(6,14): error TS2300: Duplicate identifier 'Foo'.
==== /types.ts (0 errors) ====
export interface Foo {
a: number;
}
==== /foo.js (2 errors) ====
/**
* @import { Foo } from "./types"
~~~
!!! error TS2300: Duplicate identifier 'Foo'.
*/
/**
* @import { Foo } from "./types"
~~~
!!! error TS2300: Duplicate identifier 'Foo'.
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
@@ -0,0 +1,26 @@
//// [tests/cases/conformance/jsdoc/importTag4.ts] ////
=== /types.ts ===
export interface Foo {
>Foo : Symbol(Foo, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(Foo.a, Decl(types.ts, 0, 22))
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>foo : Symbol(foo, Decl(foo.js, 11, 11))
@@ -0,0 +1,24 @@
//// [tests/cases/conformance/jsdoc/importTag4.ts] ////
=== /types.ts ===
export interface Foo {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : (foo: Foo) => void
>foo : Foo
+33
View File
@@ -0,0 +1,33 @@
//// [tests/cases/conformance/jsdoc/importTag5.ts] ////
//// [types.ts]
export interface Foo {
a: number;
}
//// [foo.js]
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
//// [types.d.ts]
export interface Foo {
a: number;
}
//// [foo.d.ts]
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
declare function f(foo: Foo): void;
import type { Foo } from "./types";
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/jsdoc/importTag5.ts] ////
=== /types.ts ===
export interface Foo {
>Foo : Symbol(Foo, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(Foo.a, Decl(types.ts, 0, 22))
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>foo : Symbol(foo, Decl(foo.js, 7, 11))
@@ -0,0 +1,20 @@
//// [tests/cases/conformance/jsdoc/importTag5.ts] ////
=== /types.ts ===
export interface Foo {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
>f : (foo: Foo) => void
>foo : Foo
@@ -0,0 +1,33 @@
//// [tests/cases/conformance/jsdoc/importTag6.ts] ////
=== /types.ts ===
export interface A {
>A : Symbol(A, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(A.a, Decl(types.ts, 0, 20))
}
export interface B {
>B : Symbol(B, Decl(types.ts, 2, 1))
a: number;
>a : Symbol(B.a, Decl(types.ts, 3, 20))
}
=== /foo.js ===
/**
* @import {
* A,
* B,
* } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>a : Symbol(a, Decl(foo.js, 11, 11))
>b : Symbol(b, Decl(foo.js, 11, 13))
@@ -0,0 +1,29 @@
//// [tests/cases/conformance/jsdoc/importTag6.ts] ////
=== /types.ts ===
export interface A {
a: number;
>a : number
}
export interface B {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import {
* A,
* B,
* } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : (a: * A, b: * B) => void
>a : * A
>b : * B
@@ -0,0 +1,32 @@
//// [tests/cases/conformance/jsdoc/importTag7.ts] ////
=== /types.ts ===
export interface A {
>A : Symbol(A, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(A.a, Decl(types.ts, 0, 20))
}
export interface B {
>B : Symbol(B, Decl(types.ts, 2, 1))
a: number;
>a : Symbol(B.a, Decl(types.ts, 3, 20))
}
=== /foo.js ===
/**
* @import {
* A,
* B } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>a : Symbol(a, Decl(foo.js, 10, 11))
>b : Symbol(b, Decl(foo.js, 10, 13))
@@ -0,0 +1,28 @@
//// [tests/cases/conformance/jsdoc/importTag7.ts] ////
=== /types.ts ===
export interface A {
a: number;
>a : number
}
export interface B {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import {
* A,
* B } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : (a: * A, b: * B) => void
>a : * A
>b : * B
@@ -0,0 +1,32 @@
//// [tests/cases/conformance/jsdoc/importTag8.ts] ////
=== /types.ts ===
export interface A {
>A : Symbol(A, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(A.a, Decl(types.ts, 0, 20))
}
export interface B {
>B : Symbol(B, Decl(types.ts, 2, 1))
a: number;
>a : Symbol(B.a, Decl(types.ts, 3, 20))
}
=== /foo.js ===
/**
* @import
* { A, B }
* from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>a : Symbol(a, Decl(foo.js, 10, 11))
>b : Symbol(b, Decl(foo.js, 10, 13))
@@ -0,0 +1,28 @@
//// [tests/cases/conformance/jsdoc/importTag8.ts] ////
=== /types.ts ===
export interface A {
a: number;
>a : number
}
export interface B {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import
* { A, B }
* from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
>f : (a: A, b: B) => void
>a : A
>b : B
@@ -0,0 +1,32 @@
//// [tests/cases/conformance/jsdoc/importTag9.ts] ////
=== /types.ts ===
export interface A {
>A : Symbol(A, Decl(types.ts, 0, 0))
a: number;
>a : Symbol(A.a, Decl(types.ts, 0, 20))
}
export interface B {
>B : Symbol(B, Decl(types.ts, 2, 1))
a: number;
>a : Symbol(B.a, Decl(types.ts, 3, 20))
}
=== /foo.js ===
/**
* @import
* * as types
* from "./types"
*/
/**
* @param { types.A } a
* @param { types.B } b
*/
function f(a, b) {}
>f : Symbol(f, Decl(foo.js, 0, 0))
>a : Symbol(a, Decl(foo.js, 10, 11))
>b : Symbol(b, Decl(foo.js, 10, 13))
@@ -0,0 +1,28 @@
//// [tests/cases/conformance/jsdoc/importTag9.ts] ////
=== /types.ts ===
export interface A {
a: number;
>a : number
}
export interface B {
a: number;
>a : number
}
=== /foo.js ===
/**
* @import
* * as types
* from "./types"
*/
/**
* @param { types.A } a
* @param { types.B } b
*/
function f(a, b) {}
>f : (a: types.A, b: types.B) => void
>a : types.A
>b : types.B
@@ -0,0 +1,48 @@
// === Completions ===
=== /b.js ===
// /**
// * @import { } from "./a"
// ^
// | ----------------------------------------------------------------------
// | interface A
// | ----------------------------------------------------------------------
// */
[
{
"marker": {
"fileName": "/b.js",
"position": 17,
"name": ""
},
"item": {
"flags": 0,
"isGlobalCompletion": false,
"isMemberCompletion": true,
"isNewIdentifierLocation": false,
"entries": [
{
"name": "A",
"kind": "interface",
"kindModifiers": "export",
"sortText": "11",
"displayParts": [
{
"text": "interface",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "A",
"kind": "interfaceName"
}
],
"documentation": []
}
]
}
}
]
@@ -0,0 +1,51 @@
// === Completions ===
=== /tests/cases/fourslash/./c.js ===
// /**
// * @import * as types from "./"
// ^
// | ----------------------------------------------------------------------
// | a
// | b
// | ----------------------------------------------------------------------
// */
[
{
"marker": {
"fileName": "/tests/cases/fourslash/./c.js",
"position": 34,
"name": ""
},
"item": {
"isGlobalCompletion": false,
"isMemberCompletion": false,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "a",
"kind": "script",
"kindModifiers": ".ts",
"sortText": "11",
"displayParts": [
{
"text": "a",
"kind": "text"
}
]
},
{
"name": "b",
"kind": "script",
"kindModifiers": ".ts",
"sortText": "11",
"displayParts": [
{
"text": "b",
"kind": "text"
}
]
}
]
}
}
]
@@ -40,6 +40,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -136,6 +137,7 @@
// | @host
// | @ignore
// | @implements
// | @import
// | @inheritdoc
// | @inner
// | @instance
@@ -229,6 +231,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -327,6 +330,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -427,6 +431,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -522,6 +527,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -618,6 +624,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -714,6 +721,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -809,6 +817,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -905,6 +914,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -998,6 +1008,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1092,6 +1103,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1186,6 +1198,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1279,6 +1292,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1374,6 +1388,7 @@
// | @host
// | @ignore
// | @implements
// | @import
// | @inheritdoc
// | @inner
// | @instance
@@ -1467,6 +1482,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1562,6 +1578,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -2096,6 +2113,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -3215,6 +3245,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -4334,6 +4377,19 @@
],
"documentation": []
},
{
"name": "@import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "@import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "@inheritdoc",
"kind": "",
@@ -5440,6 +5496,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -6546,6 +6615,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -7652,6 +7734,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -8771,6 +8866,19 @@
],
"documentation": []
},
{
"name": "@import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "@import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "@inheritdoc",
"kind": "",
@@ -9877,6 +9985,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -10983,6 +11104,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -12089,6 +12223,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -13195,6 +13342,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -14301,6 +14461,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -15407,6 +15580,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -16513,6 +16699,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -17632,6 +17831,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -18738,6 +18950,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -19844,6 +20069,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -40,6 +40,7 @@
// | @host
// | @ignore
// | @implements
// | @import
// | @inheritdoc
// | @inner
// | @instance
@@ -133,6 +134,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -231,6 +233,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -323,6 +326,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -416,6 +420,7 @@
// | @host
// | @ignore
// | @implements
// | @import
// | @inheritdoc
// | @inner
// | @instance
@@ -948,6 +953,19 @@
],
"documentation": []
},
{
"name": "@import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "@import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "@inheritdoc",
"kind": "",
@@ -2056,6 +2074,19 @@
],
"documentation": []
},
{
"name": "@import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "@import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "@inheritdoc",
"kind": "",
@@ -3164,6 +3195,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -4272,6 +4316,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -5380,6 +5437,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -40,6 +40,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -131,6 +132,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -223,6 +225,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -318,6 +321,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -413,6 +417,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -506,6 +511,7 @@
// | host
// | ignore
// | implements
// | import
// | inheritdoc
// | inner
// | instance
@@ -1039,6 +1045,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -2145,6 +2164,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -3251,6 +3283,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -4357,6 +4402,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -5463,6 +5521,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -6569,6 +6640,19 @@
],
"documentation": []
},
{
"name": "import",
"kind": "",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "import",
"kind": "text"
}
],
"documentation": []
},
{
"name": "inheritdoc",
"kind": "",
@@ -0,0 +1,10 @@
// === findRenameLocations ===
// === /a.js ===
// /**
// * <|@import { /*START PREFIX*/A as [|ARENAME|] } from "./b";
// |>*/
//
// /**
// * @param { [|ARENAME|]/*RENAME*/ } a
// */
// function f(a) {}
@@ -0,0 +1,18 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface Foo {
a: number;
}
// @filename: /foo.js
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
@@ -0,0 +1,8 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /foo.js
/**
* @import
*/
@@ -0,0 +1,8 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /foo.js
/**
* @import foo
*/
@@ -0,0 +1,8 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /foo.js
/**
* @import foo from
*/
@@ -0,0 +1,11 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface Foo {
a: number;
}
// @filename: /foo.js
/** @import x = require("types") */
@@ -0,0 +1,6 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /foo.js
/** @import * as f from "./foo" with */
@@ -0,0 +1,15 @@
// @declaration: true
// @emitDeclarationOnly: true
// @module: esnext,es2015
// @checkJs: true
// @allowJs: true
// @filename: 0.ts
export interface I { }
// @filename: 1.js
/** @import { I } from './0' with { type: "json" } */
/** @import * as foo from './0' with { type: "json" } */
/** @param {I} a */
function f(a) {}
@@ -0,0 +1,17 @@
// @declaration: true
// @emitDeclarationOnly: true
// @checkJs: true
// @allowJs: true
// @filename: a.ts
export default interface Foo {}
export interface I {}
// @filename: b.js
/** @import Foo, { I } from "./a" */
/**
* @param {Foo} a
* @param {I} b
*/
export function foo(a, b) {}
@@ -0,0 +1,18 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface Foo {
a: number;
}
// @filename: /foo.js
/**
* @import * as types from "./types"
*/
/**
* @param { types.Foo } foo
*/
export function f(foo) {}
@@ -0,0 +1,18 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export default interface Foo {
a: number;
}
// @filename: /foo.js
/**
* @import Foo from "./types"
*/
/**
* @param { Foo } foo
*/
export function f(foo) {}
@@ -0,0 +1,22 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface Foo {
a: number;
}
// @filename: /foo.js
/**
* @import { Foo } from "./types"
*/
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
@@ -0,0 +1,19 @@
// @checkJs: true
// @allowJs: true
// @declaration: true
// @emitDeclarationOnly: true
// @filename: /types.ts
export interface Foo {
a: number;
}
// @filename: /foo.js
/**
* @import { Foo } from "./types"
*/
/**
* @param { Foo } foo
*/
function f(foo) {}
@@ -0,0 +1,25 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface A {
a: number;
}
export interface B {
a: number;
}
// @filename: /foo.js
/**
* @import {
* A,
* B,
* } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
@@ -0,0 +1,24 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface A {
a: number;
}
export interface B {
a: number;
}
// @filename: /foo.js
/**
* @import {
* A,
* B } from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}
@@ -0,0 +1,24 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @filename: /types.ts
export interface A {
a: number;
}
export interface B {
a: number;
}
// @filename: /foo.js
/**
* @import
* { A, B }
* from "./types"
*/
/**
* @param { A } a
* @param { B } b
*/
function f(a, b) {}

Some files were not shown because too many files have changed in this diff Show More