Skip to content

Commit 967d618

Browse files
authored
Add lint error for declarations marked internal, but unexported (#58229)
1 parent 904a59f commit 967d618

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

scripts/eslint/rules/jsdoc-format.cjs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = createRule({
1111
internalCommentNotLastError: `@internal should only appear in final JSDoc comment for declaration.`,
1212
multipleJSDocError: `Declaration has multiple JSDoc comments.`,
1313
internalCommentOnParameterProperty: `@internal cannot appear on a JSDoc comment; use a declared property and an assignment in the constructor instead.`,
14+
internalCommentOnUnexported: `@internal should not appear on an unexported declaration.`,
1415
},
1516
schema: [],
1617
type: "problem",
@@ -23,6 +24,31 @@ module.exports = createRule({
2324
const atInternal = "@internal";
2425
const jsdocStart = "/**";
2526

27+
/** @type {Map<import("@typescript-eslint/utils").TSESTree.Node, boolean>} */
28+
const isExportedCache = new Map();
29+
30+
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
31+
function isExported(node) {
32+
const exported = isExportedCache.get(node);
33+
if (exported !== undefined) {
34+
return exported;
35+
}
36+
37+
/** @type {import("@typescript-eslint/utils").TSESTree.Node | undefined} */
38+
let current = node;
39+
while (current) {
40+
// https://github.com/typescript-eslint/typescript-eslint/blob/e44a1a280f08f9fd0d29f74e5c3e73b7b64a9606/packages/eslint-plugin/src/util/collectUnusedVariables.ts#L440
41+
if (current.type.startsWith("Export")) {
42+
isExportedCache.set(node, true);
43+
return true;
44+
}
45+
isExportedCache.set(current, false);
46+
current = current.parent;
47+
}
48+
49+
return false;
50+
}
51+
2652
/** @type {(text: string) => boolean} */
2753
function isJSDocText(text) {
2854
return text.startsWith(jsdocStart);
@@ -81,12 +107,15 @@ module.exports = createRule({
81107
if (!isJSDoc) {
82108
context.report({ messageId: "internalCommentInNonJSDocError", node: c, loc: getAtInternalLoc(c, indexInComment) });
83109
}
84-
else if (i !== last) {
85-
context.report({ messageId: "internalCommentNotLastError", node: c, loc: getAtInternalLoc(c, indexInComment) });
86-
}
87110
else if (node.type === "TSParameterProperty") {
88111
context.report({ messageId: "internalCommentOnParameterProperty", node: c, loc: getAtInternalLoc(c, indexInComment) });
89112
}
113+
else if (!isExported(node)) {
114+
context.report({ messageId: "internalCommentOnUnexported", node: c, loc: getAtInternalLoc(c, indexInComment) });
115+
}
116+
else if (i !== last) {
117+
context.report({ messageId: "internalCommentNotLastError", node: c, loc: getAtInternalLoc(c, indexInComment) });
118+
}
90119
}
91120
};
92121

src/compiler/scanner.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2805,13 +2805,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
28052805
}
28062806
}
28072807

2808-
/** @internal */
28092808
function codePointAt(s: string, i: number): number {
28102809
// TODO(jakebailey): this is wrong and should have ?? 0; but all users are okay with it
28112810
return s.codePointAt(i)!;
28122811
}
28132812

2814-
/** @internal */
28152813
function charSize(ch: number) {
28162814
if (ch >= 0x10000) {
28172815
return 2;

src/services/services.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ class IdentifierObject extends TokenOrIdentifierObject<SyntaxKind.Identifier> im
787787
declare _declarationBrand: any;
788788
declare _jsdocContainerBrand: any;
789789
declare _flowContainerBrand: any;
790-
/** @internal */ typeArguments!: NodeArray<TypeNode>;
790+
typeArguments!: NodeArray<TypeNode>;
791791
constructor(kind: SyntaxKind.Identifier, pos: number, end: number) {
792792
super(kind, pos, end);
793793
}

0 commit comments

Comments
 (0)