mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 10:41:56 -05:00
@typedef: Improve error spans from declaration emit (#42501)
* @typedef: Improve error spans from declaration emit This is a proof-of-concept fix. I think it could be expanded for all of jsdoc, but I only set it up for jsdoc type aliases. It could use a lot of polish too. * track error node in isSymbolAccessible instead * Switch to using enclosingDeclaration Remove trueErrorNode * add test of @callback and @enum * Better error + fix @enum error Since enums don't have a name property, you *have* to call `getNameOfDeclaration` to go looking through the AST for one.
This commit is contained in:
committed by
GitHub
parent
517f32940a
commit
d2443a5df1
@@ -4183,7 +4183,8 @@ namespace ts {
|
||||
return {
|
||||
accessibility: SymbolAccessibility.CannotBeNamed,
|
||||
errorSymbolName: symbolToString(symbol, enclosingDeclaration, meaning),
|
||||
errorModuleName: symbolToString(symbolExternalModule)
|
||||
errorModuleName: symbolToString(symbolExternalModule),
|
||||
errorNode: isInJSFile(enclosingDeclaration) ? enclosingDeclaration : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4699,7 +4700,7 @@ namespace ts {
|
||||
|
||||
function createMappedTypeNodeFromType(type: MappedType) {
|
||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||
const readonlyToken = type.declaration.readonlyToken ? <ReadonlyToken | PlusToken | MinusToken>factory.createToken(type.declaration.readonlyToken.kind) : undefined;
|
||||
const readonlyToken = type.declaration.readonlyToken ? <ReadonlyKeyword | PlusToken | MinusToken>factory.createToken(type.declaration.readonlyToken.kind) : undefined;
|
||||
const questionToken = type.declaration.questionToken ? <QuestionToken | PlusToken | MinusToken>factory.createToken(type.declaration.questionToken.kind) : undefined;
|
||||
let appropriateConstraintTypeNode: TypeNode;
|
||||
if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
|
||||
@@ -6183,7 +6184,7 @@ namespace ts {
|
||||
tracker: {
|
||||
...oldcontext.tracker,
|
||||
trackSymbol: (sym, decl, meaning) => {
|
||||
const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeALiases*/ false);
|
||||
const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeAliases*/ false);
|
||||
if (accessibleResult.accessibility === SymbolAccessibility.Accessible) {
|
||||
// Lookup the root symbol of the chain of refs we'll use to access it and serialize it
|
||||
const chain = lookupSymbolChainWorker(sym, context, meaning);
|
||||
@@ -6625,16 +6626,17 @@ namespace ts {
|
||||
function addResult(node: Statement, additionalModifierFlags: ModifierFlags) {
|
||||
if (canHaveModifiers(node)) {
|
||||
let newModifierFlags: ModifierFlags = ModifierFlags.None;
|
||||
const enclosingDeclaration = context.enclosingDeclaration &&
|
||||
(isJSDocTypeAlias(context.enclosingDeclaration) ? getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration);
|
||||
if (additionalModifierFlags & ModifierFlags.Export &&
|
||||
context.enclosingDeclaration &&
|
||||
(isExportingScope(context.enclosingDeclaration) || isModuleDeclaration(context.enclosingDeclaration)) &&
|
||||
enclosingDeclaration && (isExportingScope(enclosingDeclaration) || isModuleDeclaration(enclosingDeclaration)) &&
|
||||
canHaveExportModifier(node)
|
||||
) {
|
||||
// Classes, namespaces, variables, functions, interfaces, and types should all be `export`ed in a module context if not private
|
||||
newModifierFlags |= ModifierFlags.Export;
|
||||
}
|
||||
if (addingDeclare && !(newModifierFlags & ModifierFlags.Export) &&
|
||||
(!context.enclosingDeclaration || !(context.enclosingDeclaration.flags & NodeFlags.Ambient)) &&
|
||||
(!enclosingDeclaration || !(enclosingDeclaration.flags & NodeFlags.Ambient)) &&
|
||||
(isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node) || isModuleDeclaration(node))) {
|
||||
// Classes, namespaces, variables, enums, and functions all need `declare` modifiers to be valid in a declaration file top-level scope
|
||||
newModifierFlags |= ModifierFlags.Ambient;
|
||||
@@ -6657,6 +6659,8 @@ namespace ts {
|
||||
const commentText = jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined;
|
||||
const oldFlags = context.flags;
|
||||
context.flags |= NodeBuilderFlags.InTypeAlias;
|
||||
const oldEnclosingDecl = context.enclosingDeclaration;
|
||||
context.enclosingDeclaration = jsdocAliasDecl;
|
||||
const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression
|
||||
&& isJSDocTypeExpression(jsdocAliasDecl.typeExpression)
|
||||
&& serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled)
|
||||
@@ -6666,6 +6670,7 @@ namespace ts {
|
||||
!commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]
|
||||
), modifierFlags);
|
||||
context.flags = oldFlags;
|
||||
context.enclosingDeclaration = oldEnclosingDecl;
|
||||
}
|
||||
|
||||
function serializeInterface(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
|
||||
|
||||
@@ -3537,6 +3537,10 @@
|
||||
"category": "Error",
|
||||
"code": 4083
|
||||
},
|
||||
"Exported type alias '{0}' has or is using private name '{1}' from module {2}.": {
|
||||
"category": "Error",
|
||||
"code": 4084
|
||||
},
|
||||
"Conflicting definitions for '{0}' found at '{1}' and '{2}'. Consider installing a specific version of this library to resolve the conflict.": {
|
||||
"category": "Error",
|
||||
"code": 4090
|
||||
|
||||
@@ -217,12 +217,12 @@ namespace ts {
|
||||
|
||||
function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) {
|
||||
const oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
getSymbolAccessibilityDiagnostic = (s) => ({
|
||||
getSymbolAccessibilityDiagnostic = (s) => (s.errorNode && canProduceDiagnostics(s.errorNode) ? createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({
|
||||
diagnosticMessage: s.errorModuleName
|
||||
? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit
|
||||
: Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit,
|
||||
errorNode: s.errorNode || sourceFile
|
||||
});
|
||||
}));
|
||||
const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled);
|
||||
getSymbolAccessibilityDiagnostic = oldDiag;
|
||||
return result;
|
||||
|
||||
@@ -27,7 +27,10 @@ namespace ts {
|
||||
| TypeAliasDeclaration
|
||||
| ConstructorDeclaration
|
||||
| IndexSignatureDeclaration
|
||||
| PropertyAccessExpression;
|
||||
| PropertyAccessExpression
|
||||
| JSDocTypedefTag
|
||||
| JSDocCallbackTag
|
||||
| JSDocEnumTag;
|
||||
|
||||
export function canProduceDiagnostics(node: Node): node is DeclarationDiagnosticProducing {
|
||||
return isVariableDeclaration(node) ||
|
||||
@@ -48,7 +51,8 @@ namespace ts {
|
||||
isTypeAliasDeclaration(node) ||
|
||||
isConstructorDeclaration(node) ||
|
||||
isIndexSignatureDeclaration(node) ||
|
||||
isPropertyAccessExpression(node);
|
||||
isPropertyAccessExpression(node) ||
|
||||
isJSDocTypeAlias(node);
|
||||
}
|
||||
|
||||
export function createGetSymbolAccessibilityDiagnosticForNodeName(node: DeclarationDiagnosticProducing) {
|
||||
@@ -124,7 +128,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined {
|
||||
export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): GetSymbolAccessibilityDiagnostic {
|
||||
if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isPropertyAccessExpression(node) || isBindingElement(node) || isConstructorDeclaration(node)) {
|
||||
return getVariableDeclarationTypeVisibilityError;
|
||||
}
|
||||
@@ -149,7 +153,7 @@ namespace ts {
|
||||
else if (isImportEqualsDeclaration(node)) {
|
||||
return getImportEntityNameVisibilityError;
|
||||
}
|
||||
else if (isTypeAliasDeclaration(node)) {
|
||||
else if (isTypeAliasDeclaration(node) || isJSDocTypeAlias(node)) {
|
||||
return getTypeAliasDeclarationVisibilityError;
|
||||
}
|
||||
else {
|
||||
@@ -474,11 +478,13 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function getTypeAliasDeclarationVisibilityError(): SymbolAccessibilityDiagnostic {
|
||||
function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
|
||||
return {
|
||||
diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
|
||||
errorNode: (node as TypeAliasDeclaration).type,
|
||||
typeName: (node as TypeAliasDeclaration).name
|
||||
diagnosticMessage: symbolAccessibilityResult.errorModuleName
|
||||
? Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1_from_module_2
|
||||
: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
|
||||
errorNode: isJSDocTypeAlias(node) ? Debug.checkDefined(node.typeExpression) : (node as TypeAliasDeclaration).type,
|
||||
typeName: isJSDocTypeAlias(node) ? getNameOfDeclaration(node) : (node as TypeAliasDeclaration).name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user