Add lint error for declarations marked internal, but unexported (#58229)

This commit is contained in:
Jake Bailey 2024-04-17 13:52:31 -07:00 committed by GitHub
parent 904a59f343
commit 967d6189a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 6 deletions

View File

@ -11,6 +11,7 @@ module.exports = createRule({
internalCommentNotLastError: `@internal should only appear in final JSDoc comment for declaration.`,
multipleJSDocError: `Declaration has multiple JSDoc comments.`,
internalCommentOnParameterProperty: `@internal cannot appear on a JSDoc comment; use a declared property and an assignment in the constructor instead.`,
internalCommentOnUnexported: `@internal should not appear on an unexported declaration.`,
},
schema: [],
type: "problem",
@ -23,6 +24,31 @@ module.exports = createRule({
const atInternal = "@internal";
const jsdocStart = "/**";
/** @type {Map<import("@typescript-eslint/utils").TSESTree.Node, boolean>} */
const isExportedCache = new Map();
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
function isExported(node) {
const exported = isExportedCache.get(node);
if (exported !== undefined) {
return exported;
}
/** @type {import("@typescript-eslint/utils").TSESTree.Node | undefined} */
let current = node;
while (current) {
// https://github.com/typescript-eslint/typescript-eslint/blob/e44a1a280f08f9fd0d29f74e5c3e73b7b64a9606/packages/eslint-plugin/src/util/collectUnusedVariables.ts#L440
if (current.type.startsWith("Export")) {
isExportedCache.set(node, true);
return true;
}
isExportedCache.set(current, false);
current = current.parent;
}
return false;
}
/** @type {(text: string) => boolean} */
function isJSDocText(text) {
return text.startsWith(jsdocStart);
@ -81,12 +107,15 @@ module.exports = createRule({
if (!isJSDoc) {
context.report({ messageId: "internalCommentInNonJSDocError", node: c, loc: getAtInternalLoc(c, indexInComment) });
}
else if (i !== last) {
context.report({ messageId: "internalCommentNotLastError", node: c, loc: getAtInternalLoc(c, indexInComment) });
}
else if (node.type === "TSParameterProperty") {
context.report({ messageId: "internalCommentOnParameterProperty", node: c, loc: getAtInternalLoc(c, indexInComment) });
}
else if (!isExported(node)) {
context.report({ messageId: "internalCommentOnUnexported", node: c, loc: getAtInternalLoc(c, indexInComment) });
}
else if (i !== last) {
context.report({ messageId: "internalCommentNotLastError", node: c, loc: getAtInternalLoc(c, indexInComment) });
}
}
};

View File

@ -2805,13 +2805,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
}
}
/** @internal */
function codePointAt(s: string, i: number): number {
// TODO(jakebailey): this is wrong and should have ?? 0; but all users are okay with it
return s.codePointAt(i)!;
}
/** @internal */
function charSize(ch: number) {
if (ch >= 0x10000) {
return 2;

View File

@ -787,7 +787,7 @@ class IdentifierObject extends TokenOrIdentifierObject<SyntaxKind.Identifier> im
declare _declarationBrand: any;
declare _jsdocContainerBrand: any;
declare _flowContainerBrand: any;
/** @internal */ typeArguments!: NodeArray<TypeNode>;
typeArguments!: NodeArray<TypeNode>;
constructor(kind: SyntaxKind.Identifier, pos: number, end: number) {
super(kind, pos, end);
}