diff --git a/tsc/internal/parser/parser.go b/tsc/internal/parser/parser.go index d969c8a98ef70..4e313a6a4b2a2 100644 --- a/tsc/internal/parser/parser.go +++ b/tsc/internal/parser/parser.go @@ -3301,6 +3301,7 @@ func (p *Parser) parseTypeParameters() *ast.NodeList { func (p *Parser) parseTypeParameter() *ast.Node { pos := p.nodePos() + jsdoc := p.jsdocScannerInfo() modifiers := p.parseModifiersEx(false /*allowDecorators*/, true /*permitConstAsModifier*/, false /*stopOnStartOfClassStaticBlock*/) name := p.parseIdentifier() var constraint *ast.TypeNode @@ -3328,7 +3329,8 @@ func (p *Parser) parseTypeParameter() *ast.Node { defaultType = p.parseType() } result := p.factory.NewTypeParameterDeclaration(modifiers, name, constraint, expression, defaultType) - return p.finishNode(result, pos) + p.withJSDoc(p.finishNode(result, pos), jsdoc) + return result } func (p *Parser) parseParameters(flags ParseFlags) *ast.NodeList { diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index e8e6c0b22c5f1..32b796d1f2bd5 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -189,12 +189,31 @@ func (tx *DeclarationTransformer) isInternalDeclaration(node *ast.Node, sourceFi return false } - for commentRange := range tx.getLeadingCommentRangesOfNode(parseTreeNode, sourceFile) { - if hasInternalAnnotation(commentRange, sourceFile) { - return true + for _, jsdoc := range parseTreeNode.JSDoc(sourceFile) { + if tags := jsdoc.AsJSDoc().Tags; tags != nil { + for _, tag := range tags.Nodes { + if tag.TagName().Text() == "internal" { + return true + } + } } } - return false + + // Preserve explicit non-JSDoc annotations on the nearest leading comment. + var lastComment ast.CommentRange + for commentRange := range tx.getLeadingCommentRangesOfNode(parseTreeNode, sourceFile) { + lastComment = commentRange + } + if lastComment.End() == 0 { + return false + } + comment := sourceFile.Text()[lastComment.Pos():lastComment.End()] + if strings.HasPrefix(comment, "/**") { + return false + } + comment = strings.TrimLeft(strings.TrimSuffix(comment[2:], "*/"), "* \t\r\n") + words := strings.Fields(comment) + return len(words) > 0 && words[0] == "@internal" } func (tx *DeclarationTransformer) getLeadingCommentRangesOfNode(node *ast.Node, sourceFile *ast.SourceFile) iter.Seq[ast.CommentRange] { diff --git a/tsc/testdata/baselines/reference/compiler/stripInternalUnrelatedComments.js b/tsc/testdata/baselines/reference/compiler/stripInternalUnrelatedComments.js new file mode 100644 index 0000000000000..51aa3517937a4 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/stripInternalUnrelatedComments.js @@ -0,0 +1,117 @@ +//// [tests/cases/compiler/stripInternalUnrelatedComments.ts] //// + +//// [unrelated.ts] +export class Foo { + /** + * Should be stripped. + * @internal + */ + shouldBeStripped = 1; + + // TODO: maybe make this @internal? + + /** + * Public member. + */ + shouldNotBeStripped = 2; + + // sure wish I had @internal support! anyway... + mentionedInLineComment = 3; + + /* TODO: maybe make this @internal? */ + mentionedInBlockComment = 4; + + /** Public documentation mentioning `@internal`. */ + mentionedInJSDocText = 5; + + /** @internal */ + internal = 6; + + public = 7; + + // @internal + internalLineAnnotation = 8; + + /* @internal */ + internalBlockAnnotation = 9; + + /** @internal */ + /** Additional documentation. */ + internalWithMultipleJSDocComments = 10; + + /** @internalOther */ + publicWithOtherTag = 11; + + // @internal + /** Public documentation. */ + publicAfterUnrelatedAnnotation = 12; +} + +/** @internal */ +export const x = 1; + +// TODO: maybe make this @internal? +/** Public declaration. */ +export const publicValue = 2; + +export class InternalTypeParameter< + /** @internal */ T = unknown, + U = unknown +> {} + +export class PublicTypeParameters< + // TODO: maybe make this @internal? + /** Public type parameter. */ + T = unknown, + /** Public documentation mentioning `@internal`. */ + U = unknown +> {} + +//// [unrelatedJs.js] +export class Bar { + /** @internal */ + internal = 1; + + // TODO: maybe make this @internal? + /** Public member. */ + public = 2; + + // sure wish I had @internal support! anyway... + mentionedInLineComment = 3; +} + + + + +//// [unrelated.d.ts] +export declare class Foo { + /** + * Public member. + */ + shouldNotBeStripped: number; + mentionedInLineComment: number; + mentionedInBlockComment: number; + /** Public documentation mentioning `@internal`. */ + mentionedInJSDocText: number; + public: number; + /** @internalOther */ + publicWithOtherTag: number; + /** Public documentation. */ + publicAfterUnrelatedAnnotation: number; +} +/** Public declaration. */ +export declare const publicValue = 2; +export declare class InternalTypeParameter { +} +export declare class PublicTypeParameters< +/** Public type parameter. */ +T = unknown, +/** Public documentation mentioning `@internal`. */ +U = unknown> { +} +//// [unrelatedJs.d.ts] +export declare class Bar { + /** Public member. */ + public: number; + mentionedInLineComment: number; +} diff --git a/tsc/testdata/tests/cases/compiler/stripInternalUnrelatedComments.ts b/tsc/testdata/tests/cases/compiler/stripInternalUnrelatedComments.ts new file mode 100644 index 0000000000000..749272a065ab0 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/stripInternalUnrelatedComments.ts @@ -0,0 +1,87 @@ +// @target: es2015 +// @declaration: true +// @emitDeclarationOnly: true +// @stripInternal: true +// @allowJs: true +// @outDir: out +// @noTypesAndSymbols: true + +// @filename: unrelated.ts +export class Foo { + /** + * Should be stripped. + * @internal + */ + shouldBeStripped = 1; + + // TODO: maybe make this @internal? + + /** + * Public member. + */ + shouldNotBeStripped = 2; + + // sure wish I had @internal support! anyway... + mentionedInLineComment = 3; + + /* TODO: maybe make this @internal? */ + mentionedInBlockComment = 4; + + /** Public documentation mentioning `@internal`. */ + mentionedInJSDocText = 5; + + /** @internal */ + internal = 6; + + public = 7; + + // @internal + internalLineAnnotation = 8; + + /* @internal */ + internalBlockAnnotation = 9; + + /** @internal */ + /** Additional documentation. */ + internalWithMultipleJSDocComments = 10; + + /** @internalOther */ + publicWithOtherTag = 11; + + // @internal + /** Public documentation. */ + publicAfterUnrelatedAnnotation = 12; +} + +/** @internal */ +export const x = 1; + +// TODO: maybe make this @internal? +/** Public declaration. */ +export const publicValue = 2; + +export class InternalTypeParameter< + /** @internal */ T = unknown, + U = unknown +> {} + +export class PublicTypeParameters< + // TODO: maybe make this @internal? + /** Public type parameter. */ + T = unknown, + /** Public documentation mentioning `@internal`. */ + U = unknown +> {} + +// @filename: unrelatedJs.js +export class Bar { + /** @internal */ + internal = 1; + + // TODO: maybe make this @internal? + /** Public member. */ + public = 2; + + // sure wish I had @internal support! anyway... + mentionedInLineComment = 3; +}