From e7ff16a6b070e45a74f1b391cb388ccade549670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A7=91=F0=9F=8F=BB=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier?= Date: Mon, 7 Feb 2022 11:16:20 +0100 Subject: [PATCH] fix: remove the "comments rewriter" The comments rewriter was used to prefix documentation comments with the stability level of the associated API (e.g: `(experimental)` or `(deprecated)`). This was introduced to palliate insufficient IDE support for `@deprecated` and the mixing of `@stable` and `@experimental` APIs in CDK v1. Since then, the TypeScript language server has added support for `@deprecated` IDE features, and CDK v2 moved all `@experimental` APIs to separate packages, removing the risk for people to inadvertently take experimental dependencies. In profiling, this feature alone was attributed between 50% and 60% of the total time spent compiling `aws-cdk-lib`. The impact is likely comparable on other large construct libraries. The benefits from this feature are not sufficient to justify the cost to make it happen. Instead of trying to optimize it (which could prove impossible), decision was made to simply drop it. --- packages/jsii-calc/test/assembly.jsii | 26 +- .../__snapshots__/target-dotnet.test.ts.snap | 24 +- .../__snapshots__/target-go.test.ts.snap | 26 +- .../__snapshots__/target-java.test.ts.snap | 24 +- .../__snapshots__/target-python.test.ts.snap | 24 +- packages/jsii/lib/assembler.ts | 135 +----- packages/jsii/lib/docs.ts | 64 --- packages/jsii/lib/jsii-diagnostic.ts | 10 - .../lib/transforms/ts-comment-replacer.ts | 133 ------ .../test/__snapshots__/negatives.test.ts.snap | 14 +- packages/jsii/test/deprecated-remover.test.ts | 448 +++++++++--------- packages/jsii/test/docs.test.ts | 125 +---- 12 files changed, 300 insertions(+), 753 deletions(-) delete mode 100644 packages/jsii/lib/transforms/ts-comment-replacer.ts diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index 213c90a2fd..b38d553b9a 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -761,7 +761,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) String representation of the value." + "summary": "String representation of the value." }, "locationInModule": { "filename": "lib/calculator.ts", @@ -781,7 +781,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) The value." + "summary": "The value." }, "immutable": true, "locationInModule": { @@ -1772,7 +1772,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) Say hello!" + "summary": "Say hello!" }, "locationInModule": { "filename": "lib/calculator.ts", @@ -4764,7 +4764,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) Say hello!" + "summary": "Say hello!" }, "locationInModule": { "filename": "lib/compliance.ts", @@ -9364,7 +9364,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) String representation of the value." + "summary": "String representation of the value." }, "locationInModule": { "filename": "lib/calculator.ts", @@ -9384,7 +9384,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) The value." + "summary": "The value." }, "immutable": true, "locationInModule": { @@ -9471,7 +9471,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) Say hello!" + "summary": "Say hello!" }, "locationInModule": { "filename": "lib/calculator.ts", @@ -9488,7 +9488,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) String representation of the value." + "summary": "String representation of the value." }, "locationInModule": { "filename": "lib/calculator.ts", @@ -9508,7 +9508,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) The value." + "summary": "The value." }, "immutable": true, "locationInModule": { @@ -14787,7 +14787,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) String representation of the value." + "summary": "String representation of the value." }, "locationInModule": { "filename": "lib/calculator.ts", @@ -14825,7 +14825,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) The value." + "summary": "The value." }, "immutable": true, "locationInModule": { @@ -15075,7 +15075,7 @@ { "docs": { "stability": "stable", - "summary": "(deprecated) Say hello!" + "summary": "Say hello!" }, "locationInModule": { "filename": "lib/module2647/index.ts", @@ -16807,5 +16807,5 @@ } }, "version": "3.20.120", - "fingerprint": "w6AJ35Nh9lBusQyMGP28WJp5MNbg527uO9TsHaP+DiE=" + "fingerprint": "lt+IM5wKyCp+HghCCEt9CX5x65ePqyHvu/emNzsxqbg=" } diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap index 726a300cf1..89b11fd9fc 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap @@ -3411,14 +3411,14 @@ namespace Amazon.JSII.Tests.CalculatorNamespace { } - /// (deprecated) String representation of the value. + /// String representation of the value. [JsiiMethod(name: "toString", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public override string ToString() { return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) The value. + /// The value. [JsiiProperty(name: "value", typeJson: "{\\"primitive\\":\\"number\\"}")] public override double Value { @@ -4013,7 +4013,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace { } - /// (deprecated) Say hello! + /// Say hello! [JsiiMethod(name: "hello", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public virtual string Hello() { @@ -4902,7 +4902,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace.Composition { } - /// (deprecated) String representation of the value. + /// String representation of the value. [JsiiMethod(name: "toString", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public override string ToString() { @@ -4919,7 +4919,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace.Composition get; } - /// (deprecated) The value. + /// The value. [JsiiProperty(name: "value", typeJson: "{\\"primitive\\":\\"number\\"}")] public override double Value { @@ -6368,7 +6368,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace { } - /// (deprecated) Say hello! + /// Say hello! [JsiiMethod(name: "hello", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public virtual string Hello() { @@ -12632,7 +12632,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace.Module2647 { } - /// (deprecated) Say hello! + /// Say hello! [JsiiMethod(name: "hello", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public virtual string Hello() { @@ -13723,14 +13723,14 @@ namespace Amazon.JSII.Tests.CalculatorNamespace return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) String representation of the value. + /// String representation of the value. [JsiiMethod(name: "toString", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public override string ToString() { return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) The value. + /// The value. [JsiiProperty(name: "value", typeJson: "{\\"primitive\\":\\"number\\"}")] public override double Value { @@ -13823,21 +13823,21 @@ namespace Amazon.JSII.Tests.CalculatorNamespace return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) Say hello! + /// Say hello! [JsiiMethod(name: "hello", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public virtual string Hello() { return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) String representation of the value. + /// String representation of the value. [JsiiMethod(name: "toString", returnsJson: "{\\"type\\":{\\"primitive\\":\\"string\\"}}")] public override string ToString() { return InvokeInstanceMethod(new System.Type[]{}, new object[]{})!; } - /// (deprecated) The value. + /// The value. [JsiiProperty(name: "value", typeJson: "{\\"primitive\\":\\"number\\"}")] public override double Value { diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap index 8a5013518a..109605c061 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap @@ -2603,7 +2603,7 @@ func (j *jsiiProxy_CompositeOperation) SetStringStyle(val CompositeOperation_Com ) } -// (deprecated) String representation of the value. +// String representation of the value. func (c *jsiiProxy_CompositeOperation) ToString() *string { var returns *string @@ -3366,7 +3366,7 @@ func NewAdd_Override(a Add, lhs scopejsiicalclib.NumericValue, rhs scopejsiicalc ) } -// (deprecated) Say hello! +// Say hello! func (a *jsiiProxy_Add) Hello() *string { var returns *string @@ -3380,7 +3380,7 @@ func (a *jsiiProxy_Add) Hello() *string { return returns } -// (deprecated) String representation of the value. +// String representation of the value. func (a *jsiiProxy_Add) ToString() *string { var returns *string @@ -4379,7 +4379,7 @@ func NewBinaryOperation_Override(b BinaryOperation, lhs scopejsiicalclib.Numeric ) } -// (deprecated) Say hello! +// Say hello! func (b *jsiiProxy_BinaryOperation) Hello() *string { var returns *string @@ -4744,7 +4744,7 @@ func (c *jsiiProxy_Calculator) ReadUnionValue() *float64 { return returns } -// (deprecated) String representation of the value. +// String representation of the value. func (c *jsiiProxy_Calculator) ToString() *string { var returns *string @@ -6663,7 +6663,7 @@ func NewDoubleTrouble_Override(d DoubleTrouble) { ) } -// (deprecated) Say hello! +// Say hello! func (d *jsiiProxy_DoubleTrouble) Hello() *string { var returns *string @@ -10399,7 +10399,7 @@ func (m *jsiiProxy_Multiply) Goodbye() *string { return returns } -// (deprecated) Say hello! +// Say hello! func (m *jsiiProxy_Multiply) Hello() *string { var returns *string @@ -10427,7 +10427,7 @@ func (m *jsiiProxy_Multiply) Next() *float64 { return returns } -// (deprecated) String representation of the value. +// String representation of the value. func (m *jsiiProxy_Multiply) ToString() *string { var returns *string @@ -10547,7 +10547,7 @@ func (n *jsiiProxy_Negate) Goodbye() *string { return returns } -// (deprecated) Say hello! +// Say hello! func (n *jsiiProxy_Negate) Hello() *string { var returns *string @@ -10561,7 +10561,7 @@ func (n *jsiiProxy_Negate) Hello() *string { return returns } -// (deprecated) String representation of the value. +// String representation of the value. func (n *jsiiProxy_Negate) ToString() *string { var returns *string @@ -11568,7 +11568,7 @@ func (j *jsiiProxy_Power) SetStringStyle(val composition.CompositeOperation_Comp ) } -// (deprecated) String representation of the value. +// String representation of the value. func (p *jsiiProxy_Power) ToString() *string { var returns *string @@ -13148,7 +13148,7 @@ func (j *jsiiProxy_Sum) SetStringStyle(val composition.CompositeOperation_Compos ) } -// (deprecated) String representation of the value. +// String representation of the value. func (s *jsiiProxy_Sum) ToString() *string { var returns *string @@ -16936,7 +16936,7 @@ func (e *jsiiProxy_ExtendAndImplement) Foo(obj jcb.IBaseInterface) { ) } -// (deprecated) Say hello! +// Say hello! func (e *jsiiProxy_ExtendAndImplement) Hello() *string { var returns *string diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-java.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-java.test.ts.snap index ad5c61affa..9f790ee4a4 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-java.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-java.test.ts.snap @@ -4661,7 +4661,7 @@ public class Add extends software.amazon.jsii.tests.calculator.BinaryOperation { } /** - * (deprecated) String representation of the value. + * String representation of the value. */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -4670,7 +4670,7 @@ public class Add extends software.amazon.jsii.tests.calculator.BinaryOperation { } /** - * (deprecated) The value. + * The value. */ @Override @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @@ -5489,7 +5489,7 @@ public abstract class BinaryOperation extends software.amazon.jsii.tests.calcula } /** - * (deprecated) Say hello! + * Say hello! */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -9436,7 +9436,7 @@ public class DoubleTrouble extends software.amazon.jsii.JsiiObject implements so } /** - * (deprecated) Say hello! + * Say hello! */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -15876,7 +15876,7 @@ public class Multiply extends software.amazon.jsii.tests.calculator.BinaryOperat } /** - * (deprecated) String representation of the value. + * String representation of the value. */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -15885,7 +15885,7 @@ public class Multiply extends software.amazon.jsii.tests.calculator.BinaryOperat } /** - * (deprecated) The value. + * The value. */ @Override @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @@ -15943,7 +15943,7 @@ public class Negate extends software.amazon.jsii.tests.calculator.UnaryOperation } /** - * (deprecated) Say hello! + * Say hello! */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -15952,7 +15952,7 @@ public class Negate extends software.amazon.jsii.tests.calculator.UnaryOperation } /** - * (deprecated) String representation of the value. + * String representation of the value. */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -15961,7 +15961,7 @@ public class Negate extends software.amazon.jsii.tests.calculator.UnaryOperation } /** - * (deprecated) The value. + * The value. */ @Override @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @@ -21939,7 +21939,7 @@ public abstract class CompositeOperation extends software.amazon.jsii.tests.calc } /** - * (deprecated) String representation of the value. + * String representation of the value. */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override @@ -21956,7 +21956,7 @@ public abstract class CompositeOperation extends software.amazon.jsii.tests.calc public abstract @org.jetbrains.annotations.NotNull software.amazon.jsii.tests.calculator.lib.NumericValue getExpression(); /** - * (deprecated) The value. + * The value. */ @Override @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @@ -22526,7 +22526,7 @@ public class ExtendAndImplement extends software.amazon.jsii.tests.calculator.li } /** - * (deprecated) Say hello! + * Say hello! */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Stable) @Override diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap index f618f261c7..947dde8d37 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap @@ -3044,7 +3044,7 @@ class BinaryOperation( @jsii.member(jsii_name="hello") def hello(self) -> builtins.str: - '''(deprecated) Say hello!''' + '''Say hello!''' return typing.cast(builtins.str, jsii.invoke(self, "hello", [])) @builtins.property # type: ignore[misc] @@ -7154,13 +7154,13 @@ class Multiply( @jsii.member(jsii_name="toString") def to_string(self) -> builtins.str: - '''(deprecated) String representation of the value.''' + '''String representation of the value.''' return typing.cast(builtins.str, jsii.invoke(self, "toString", [])) @builtins.property # type: ignore[misc] @jsii.member(jsii_name="value") def value(self) -> jsii.Number: - '''(deprecated) The value.''' + '''The value.''' return typing.cast(jsii.Number, jsii.get(self, "value")) @@ -9547,13 +9547,13 @@ class Add(BinaryOperation, metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.Add"): @jsii.member(jsii_name="toString") def to_string(self) -> builtins.str: - '''(deprecated) String representation of the value.''' + '''String representation of the value.''' return typing.cast(builtins.str, jsii.invoke(self, "toString", [])) @builtins.property # type: ignore[misc] @jsii.member(jsii_name="value") def value(self) -> jsii.Number: - '''(deprecated) The value.''' + '''The value.''' return typing.cast(jsii.Number, jsii.get(self, "value")) @@ -9906,18 +9906,18 @@ class Negate(UnaryOperation, metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.Negat @jsii.member(jsii_name="hello") def hello(self) -> builtins.str: - '''(deprecated) Say hello!''' + '''Say hello!''' return typing.cast(builtins.str, jsii.invoke(self, "hello", [])) @jsii.member(jsii_name="toString") def to_string(self) -> builtins.str: - '''(deprecated) String representation of the value.''' + '''String representation of the value.''' return typing.cast(builtins.str, jsii.invoke(self, "toString", [])) @builtins.property # type: ignore[misc] @jsii.member(jsii_name="value") def value(self) -> jsii.Number: - '''(deprecated) The value.''' + '''The value.''' return typing.cast(jsii.Number, jsii.get(self, "value")) @@ -9976,7 +9976,7 @@ class DoubleTrouble(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.DoubleTrouble" @jsii.member(jsii_name="hello") def hello(self) -> builtins.str: - '''(deprecated) Say hello!''' + '''Say hello!''' return typing.cast(builtins.str, jsii.invoke(self, "hello", [])) @jsii.member(jsii_name="next") @@ -10417,7 +10417,7 @@ class CompositeOperation( @jsii.member(jsii_name="toString") def to_string(self) -> builtins.str: - '''(deprecated) String representation of the value.''' + '''String representation of the value.''' return typing.cast(builtins.str, jsii.invoke(self, "toString", [])) @builtins.property # type: ignore[misc] @@ -10433,7 +10433,7 @@ class CompositeOperation( @builtins.property # type: ignore[misc] @jsii.member(jsii_name="value") def value(self) -> jsii.Number: - '''(deprecated) The value.''' + '''The value.''' return typing.cast(jsii.Number, jsii.get(self, "value")) @builtins.property # type: ignore[misc] @@ -10803,7 +10803,7 @@ class ExtendAndImplement( @jsii.member(jsii_name="hello") def hello(self) -> builtins.str: - '''(deprecated) Say hello!''' + '''Say hello!''' return typing.cast(builtins.str, jsii.invoke(self, "hello", [])) @jsii.member(jsii_name="localMethod") diff --git a/packages/jsii/lib/assembler.ts b/packages/jsii/lib/assembler.ts index 8d8d0f79d3..0516411258 100644 --- a/packages/jsii/lib/assembler.ts +++ b/packages/jsii/lib/assembler.ts @@ -13,7 +13,6 @@ import * as ts from 'typescript'; import { getReferencedDocParams, parseSymbolDocumentation, - renderSymbolDocumentation, TypeSystemHints, } from './docs'; import { Emitter } from './emitter'; @@ -26,7 +25,6 @@ import { symbolIdentifier } from './symbol-id'; import { DeprecatedRemover } from './transforms/deprecated-remover'; import { DeprecationWarningsInjector } from './transforms/deprecation-warnings'; import { RuntimeTypeInfoInjector } from './transforms/runtime-info'; -import { TsCommentReplacer } from './transforms/ts-comment-replacer'; import { combinedTransformers } from './transforms/utils'; import { Validator } from './validator'; import { SHORT_VERSION, VERSION } from './version'; @@ -41,7 +39,6 @@ const LOG = log4js.getLogger('jsii/assembler'); * The JSII Assembler consumes a ``ts.Program`` instance and emits a JSII assembly. */ export class Assembler implements Emitter { - private readonly commentReplacer = new TsCommentReplacer(); private readonly runtimeTypeInfoInjector: RuntimeTypeInfoInjector; private readonly deprecatedRemover?: DeprecatedRemover; private readonly warningsInjector?: DeprecationWarningsInjector; @@ -132,7 +129,6 @@ export class Assembler implements Emitter { return combinedTransformers( this.deprecatedRemover?.customTransformers ?? {}, this.runtimeTypeInfoInjector.makeTransformers(), - this.commentReplacer.makeTransformers(), this.warningsInjector?.customTransformers ?? {}, ); } @@ -1520,11 +1516,6 @@ export class Assembler implements Emitter { constructor, memberEmitContext, ).docs; - this.overrideDocComment( - constructor, - jsiiType.initializer.docs, - paramDocs(jsiiType.initializer.parameters), - ); } // Process constructor-based property declarations even if constructor is private @@ -1573,8 +1564,6 @@ export class Assembler implements Emitter { this._verifyNoStaticMixing(jsiiType, type.symbol.valueDeclaration); - this.overrideDocComment(type.getSymbol(), jsiiType?.docs); - return _sortMembers(jsiiType); } @@ -1775,7 +1764,6 @@ export class Assembler implements Emitter { kind: spec.TypeKind.Enum, members: members.map((m) => { const { docs } = this._visitDocumentation(m.symbol, typeContext); - this.overrideDocComment(m.symbol, docs); return { name: m.symbol.name, docs }; }), name: symbol.name, @@ -1790,8 +1778,6 @@ export class Assembler implements Emitter { decl, ); - this.overrideDocComment(type.getSymbol(), jsiiType?.docs); - return Promise.resolve(jsiiType); } @@ -1821,12 +1807,10 @@ export class Assembler implements Emitter { _findHint(decl, 'struct')!, 'struct', 'interfaces with only readonly properties', - ) - .addRelatedInformation( - ts.getNameOfDeclaration(decl) ?? decl, - 'The annotated declaration is here', - ) - .preformat(this.projectInfo.projectRoot), + ).addRelatedInformation( + ts.getNameOfDeclaration(decl) ?? decl, + 'The annotated declaration is here', + ), ); // Clean up the bad hint... delete (result.hints as any).struct; @@ -1978,27 +1962,15 @@ export class Assembler implements Emitter { jsiiType.datatype = true; } else if (hints.struct) { this._diagnostics.push( - jsiiType.methods!.reduce( - (diag, mthod) => { - const node = bindings.getMethodRelatedNode(mthod); - return node - ? diag.addRelatedInformation( - ts.getNameOfDeclaration(node) ?? node, - `A method is declared here`, - ) - : diag; - }, - JsiiDiagnostic.JSII_7001_ILLEGAL_HINT.create( - _findHint(declaration, 'struct')!, - 'struct', - 'interfaces with only readonly properties', - ) - .addRelatedInformation( - ts.getNameOfDeclaration(declaration) ?? declaration, - 'The annotated declartion is here', - ) - .preformat(this.projectInfo.projectRoot), - ), + jsiiType.methods!.reduce((diag, mthod) => { + const node = bindings.getMethodRelatedNode(mthod); + return node + ? diag.addRelatedInformation( + ts.getNameOfDeclaration(node) ?? node, + `A method is declared here`, + ) + : diag; + }, JsiiDiagnostic.JSII_7001_ILLEGAL_HINT.create(_findHint(declaration, 'struct')!, 'struct', 'interfaces with only readonly properties').addRelatedInformation(ts.getNameOfDeclaration(declaration) ?? declaration, 'The annotated declartion is here')), ); } @@ -2101,8 +2073,6 @@ export class Assembler implements Emitter { checkNoIntersection, ); - this.overrideDocComment(type.getSymbol(), jsiiType?.docs); - return _sortMembers(jsiiType); } @@ -2242,7 +2212,6 @@ export class Assembler implements Emitter { return; } type.methods.push(method); - this.overrideDocComment(symbol, method.docs, paramDocs(method.parameters)); } private _warnAboutReservedWords(symbol: ts.Symbol) { @@ -2374,7 +2343,6 @@ export class Assembler implements Emitter { return; } type.properties.push(property); - this.overrideDocComment(symbol, property.docs); } private async _toParameter( @@ -2724,71 +2692,6 @@ export class Assembler implements Emitter { this.runtimeTypeInfoInjector.registerClassFqn(clazz, fqn); } - /** - * From the given JSIIDocs, re-render the TSDoc comment for the Node - * - * We may change the documentation a little, so that the doc comment that gets - * written is not necessarily exactly the same as the docs that go into the - * JSII manifest. - * - * This makes it possible for the code doc comments to highlight things - * slighly differently from the API Reference, and makes sure we don't - * duplicate information. - * - * Unless the docs got changed, this yields the same output back as the one that - * we originally saw (modulo whitespace changes). - */ - private overrideDocComment( - symbol?: ts.Symbol, - docs?: spec.Docs, - parameters?: Record, - ) { - if (!docs || !symbol) { - return; - } - - docs = this.docCommentDocs(docs); - - // Some symbols have multiple declarations (for example, a class + interface - // mixins, or a property declartaion + constructor argument). - // - // We DON'T wwant to put the doc comment on the constructor argument, because it - // looks silly there. - for (const decl of symbol.getDeclarations() ?? []) { - if (ts.isParameter(decl)) { - continue; - } - - this.commentReplacer.overrideNodeDocComment( - decl, - renderSymbolDocumentation(docs, parameters), - ); - } - } - - /** - * Return a potentially new set of Docs, for rendering back to a TypeScript doc comment - * - * We put the "(experimental)"/"(deprecated)" status into the doc - * comment summary, so that it's presented front and center. - */ - private docCommentDocs(docs: Readonly): spec.Docs { - // Modify the summary if this API element has a special stability - if (docs.stability === spec.Stability.Experimental && docs.summary) { - return { - ...docs, - summary: `(experimental) ${docs.summary}`, - }; - } - if (docs.stability === spec.Stability.Deprecated && docs.summary) { - return { - ...docs, - summary: `(deprecated) ${docs.summary}`, - }; - } - return docs; - } - /** * Return only those submodules from the submodules list that are submodules inside this * assembly. @@ -3344,18 +3247,6 @@ async function findPackageInfo( return findPackageInfo(parent); } -function paramDocs( - params?: readonly spec.Parameter[], -): Record { - const ret: Record = {}; - for (const param of params ?? []) { - if (param.docs) { - ret[param.name] = param.docs; - } - } - return ret; -} - /** * Checks is the provided type is "this" (as a type annotation). * diff --git a/packages/jsii/lib/docs.ts b/packages/jsii/lib/docs.ts index 05bff439a1..dde213cdc2 100644 --- a/packages/jsii/lib/docs.ts +++ b/packages/jsii/lib/docs.ts @@ -68,70 +68,6 @@ export function parseSymbolDocumentation( return parseDocParts(comment, tags); } -/** - * Render JSIIDocs back to a TSDoc block - */ -export function renderSymbolDocumentation( - docs: spec.Docs, - parameters?: Record, -): string { - const lines: string[] = []; - if (docs.summary) { - lines.push(docs.summary); - lines.push(''); - } - if (docs.remarks) { - lines.push(...docs.remarks.split('\n')); - lines.push(''); - } - - for (const [name, docs] of Object.entries(parameters ?? {})) { - tag('param', `${name} ${docs.summary ?? ''}`); - } - tag(DocTag.RETURNS, docs.returns); - tag(DocTag.DEFAULT, docs.default); - tag(DocTag.SEE, docs.see); - if (docs.subclassable) { - tag(DocTag.SUBCLASSABLE, ''); - } - - switch (docs.stability) { - case spec.Stability.Deprecated: - tag('deprecated', docs.deprecated ?? ''); - break; - case spec.Stability.Experimental: - tag('experimental', ''); - break; - case spec.Stability.External: - tag('external', ''); - break; - default: - tag('stability', docs.stability); - } - - for (const [k, v] of Object.entries(docs.custom ?? {})) { - tag(k, v); - } - - if (docs.example) { - lines.push('@example'); - lines.push(''); - lines.push(...docs.example.split('\n')); - } - - while (lines.length > 0 && lines[lines.length - 1] === '') { - lines.pop(); - } - - return lines.join('\n'); - - function tag(tagName: string, value: string | undefined) { - if (value !== undefined) { - lines.push(`@${tagName} ${value}`.trim()); - } - } -} - /** * Return the list of parameter names that are referenced in the docstring for this symbol */ diff --git a/packages/jsii/lib/jsii-diagnostic.ts b/packages/jsii/lib/jsii-diagnostic.ts index 67c6ff643e..272ac9bffc 100644 --- a/packages/jsii/lib/jsii-diagnostic.ts +++ b/packages/jsii/lib/jsii-diagnostic.ts @@ -899,16 +899,6 @@ export class JsiiDiagnostic implements ts.Diagnostic { } return this.#formatted; } - - /** - * Ensures the formatted diagnostic is prepared for later re-use. - * - * @returns `this` - */ - public preformat(projectRoot: string): this { - this.format(projectRoot); - return this; - } } export type DiagnosticMessageFormatter = ( diff --git a/packages/jsii/lib/transforms/ts-comment-replacer.ts b/packages/jsii/lib/transforms/ts-comment-replacer.ts deleted file mode 100644 index 33a33af409..0000000000 --- a/packages/jsii/lib/transforms/ts-comment-replacer.ts +++ /dev/null @@ -1,133 +0,0 @@ -import * as ts from 'typescript'; - -/** - * Machinery to replace physical doc comments in the AST with synthetic ones - * - * We use this to slightly tweak the comment blocks that we emit to the .js - * and .d.ts files. - * - * The process is as follows: - * - * - Iterate over all nodes of the AST. Do the analysis that we require, remember - * the Nodes we want to replace the comments of in a table. - * - When we're ready to emit JS/DTS, use transforms to replace the physical with - * synthetic comments by looking up the visited Nodes in the table. - * - During transformation, we are given a "shadow copy" (?) of the actual node, - * so we need to resolve it to the OriginalNode (which is the one that the assembler - * saw) -- note that only _original_ nodes have SourceFiles attached. - * - * It must be done this way because: - * - * - Comments don't have a node in the AST. Instead, comments are called "trivia" - * and are discovered by _scanning the source file between two token positions_ - * in an on-demand fashion. - * - The only way to "add" comments to a node is to call addSyntheticComment, - * which remembers the comment we'd like to emit on the EmitNode of the corresponding - * AST Node (the printer will respect this SyntheticComment when printing everything - * back out again). - * - EmitNodes are used for bookkeeping, and are cleared between different passes of - * the compiler. We can therefore not add the synthetic comments in the assembler - * pass, we have to be able to do it on-demand in a special "transform" pass. - */ -export class TsCommentReplacer { - private readonly nodes = new Map(); - - /** - * Override the doc comment of an AST node - */ - public overrideNodeDocComment(node: ts.Node, docstring: string): void { - this.nodes.set(node, { contents: docstring }); - } - - /** - * Return the set of Transformers to be used in TSC's program.emit() - */ - public makeTransformers(): ts.CustomTransformers { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const self = this; - - const transformerFactory = (ctx: ts.TransformationContext) => { - return (input: T): T => { - if (ts.isSourceFile(input)) { - return replaceSourceFile(input) as T; - } - // I don't know what a Bundle is but seems we don't need it - return input; - }; - - function replaceSourceFile(source: ts.SourceFile): ts.SourceFile { - return ts.visitEachChild(source, visitor, ctx); - - function visitor(node: ts.Node): ts.Node { - const handled = self.handleNode(node, source); - return ts.visitEachChild(handled, visitor, ctx); - } - } - }; - - return { - // This needs to be here to properly transform .js generation - before: [transformerFactory], - // This needs to be here to properly transform .d.ts generation - afterDeclarations: [transformerFactory], - }; - } - - private handleNode(node: T, source: ts.SourceFile): T { - const original = ts.getOriginalNode(node); - const doOverride = this.nodes.get(original); - - if (doOverride) { - whiteoutLeadingComments(original, source); - this.addTsdocComment(node, doOverride.contents); - } - return node; - } - - /** - * Add a synthetic comment formatted like a TSDoc block - * - * A multiline trivia comment looks like "/ * (...content...) * / (newline?)". - * - * The TypeScript printer will take care of indentation. - */ - private addTsdocComment(node: ts.Node, text: string) { - const lines = text.trim().split('\n'); - - // eslint-disable-next-line prettier/prettier - const commentContents = ['*\n', ...lines.map((l) => ` * ${l}\n`), ` `].join( - '', - ); - - ts.addSyntheticLeadingComment( - node, - ts.SyntaxKind.MultiLineCommentTrivia, - commentContents, - true, - ); - } -} - -interface NodeDocs { - readonly contents: string; -} - -/** - * In the given source file, replace the extent of the trivia with whitespace - * - * This will make it invisible when the printer calls getLeadingTrivia(), - * which will make it not render it out again. The only comments that - * will be rendered after this will be synthetic comments. - */ -function whiteoutLeadingComments(node: ts.Node, source: ts.SourceFile) { - let text = source.getFullText(); - ts.forEachLeadingCommentRange(text, node.getFullStart(), (pos, end, kind) => { - if (kind === ts.SyntaxKind.MultiLineCommentTrivia) { - text = text.slice(0, pos).padEnd(end, ' ') + text.slice(end); - } - }); - if (source.text !== text) { - source.text = text; - (source as any).lineMap = (ts as any).computeLineStarts(text); - } -} diff --git a/packages/jsii/test/__snapshots__/negatives.test.ts.snap b/packages/jsii/test/__snapshots__/negatives.test.ts.snap index fd25017d8f..cb26c92bcb 100644 --- a/packages/jsii/test/__snapshots__/negatives.test.ts.snap +++ b/packages/jsii/test/__snapshots__/negatives.test.ts.snap @@ -843,17 +843,17 @@ neg.struct-hint-on-enum.ts:4:4 - error JSII7001: Illegal use of "@struct" hint. `; exports[`struct-hint-with-methods 1`] = ` -neg.struct-hint-with-methods.ts:1:72 - error JSII7001: Illegal use of "@struct" hint. It is only valid on interfaces with only readonly properties. +neg.struct-hint-with-methods.ts:4:4 - error JSII7001: Illegal use of "@struct" hint. It is only valid on interfaces with only readonly properties. -1 - +4 * @struct + ~~~~~~~ - neg.struct-hint-with-methods.ts:2:18 - 2 export interface INotAStruct { + neg.struct-hint-with-methods.ts:6:18 + 6 export interface INotAStruct { ~~~~~~~~~~~ The annotated declartion is here - neg.struct-hint-with-methods.ts:3:3 - 3 method(): void; + neg.struct-hint-with-methods.ts:7:3 + 7 method(): void; ~~~~~~ A method is declared here diff --git a/packages/jsii/test/deprecated-remover.test.ts b/packages/jsii/test/deprecated-remover.test.ts index 302909834d..63964fbe9b 100644 --- a/packages/jsii/test/deprecated-remover.test.ts +++ b/packages/jsii/test/deprecated-remover.test.ts @@ -275,247 +275,233 @@ describe('stripDeprecatedAllowList', () => { ); expect(result.assembly.types).toMatchInlineSnapshot(` - Object { - "testpkg.Deprecated": Object { - "assembly": "testpkg", - "base": "testpkg.Retained", - "docs": Object { - "deprecated": "stripped", - "stability": "deprecated", - }, - "fqn": "testpkg.Deprecated", - "initializer": Object {}, - "interfaces": Array [ - "testpkg.IRetainedInterface", - ], - "kind": "class", - "locationInModule": Object { - "filename": "mixed.ts", - "line": 10, - }, - "name": "Deprecated", - "symbolId": "mixed:Deprecated", - }, - "testpkg.DeprecatedClass": Object { - "assembly": "testpkg", - "docs": Object { - "deprecated": "stripped", - "stability": "deprecated", - }, - "fqn": "testpkg.DeprecatedClass", - "initializer": Object {}, - "kind": "class", - "locationInModule": Object { - "filename": "deprecated.ts", - "line": 5, - }, - "name": "DeprecatedClass", - "symbolId": "deprecated:DeprecatedClass", - }, - "testpkg.DeprecatedEnum": Object { - "assembly": "testpkg", - "docs": Object { - "deprecated": "stripped", - "stability": "deprecated", - }, - "fqn": "testpkg.DeprecatedEnum", - "kind": "enum", - "locationInModule": Object { - "filename": "enums.ts", - "line": 8, - }, - "members": Array [ Object { - "docs": Object { - "stability": "deprecated", + "testpkg.Deprecated": Object { + "assembly": "testpkg", + "base": "testpkg.Retained", + "docs": Object { + "deprecated": "stripped", + "stability": "deprecated", + }, + "fqn": "testpkg.Deprecated", + "initializer": Object {}, + "interfaces": Array [ + "testpkg.IRetainedInterface", + ], + "kind": "class", + "locationInModule": Object { + "filename": "mixed.ts", + "line": 10, + }, + "name": "Deprecated", + "symbolId": "mixed:Deprecated", }, - "name": "VALUE_ONE", - }, - Object { - "docs": Object { - "stability": "deprecated", + "testpkg.DeprecatedClass": Object { + "assembly": "testpkg", + "docs": Object { + "deprecated": "stripped", + "stability": "deprecated", + }, + "fqn": "testpkg.DeprecatedClass", + "initializer": Object {}, + "kind": "class", + "locationInModule": Object { + "filename": "deprecated.ts", + "line": 5, + }, + "name": "DeprecatedClass", + "symbolId": "deprecated:DeprecatedClass", }, - "name": "VALUE_TWO", - }, - ], - "name": "DeprecatedEnum", - "symbolId": "enums:DeprecatedEnum", - }, - "testpkg.GrandChild": Object { - "assembly": "testpkg", - "base": "testpkg.Deprecated", - "fqn": "testpkg.GrandChild", - "initializer": Object {}, - "kind": "class", - "locationInModule": Object { - "filename": "mixed.ts", - "line": 11, - }, - "methods": Array [ - Object { - "locationInModule": Object { - "filename": "mixed.ts", - "line": 12, + "testpkg.DeprecatedEnum": Object { + "assembly": "testpkg", + "docs": Object { + "deprecated": "stripped", + "stability": "deprecated", + }, + "fqn": "testpkg.DeprecatedEnum", + "kind": "enum", + "locationInModule": Object { + "filename": "enums.ts", + "line": 8, + }, + "members": Array [ + Object { + "docs": Object { + "stability": "deprecated", + }, + "name": "VALUE_ONE", + }, + Object { + "docs": Object { + "stability": "deprecated", + }, + "name": "VALUE_TWO", + }, + ], + "name": "DeprecatedEnum", + "symbolId": "enums:DeprecatedEnum", }, - "name": "retainedMethod", - }, - ], - "name": "GrandChild", - "symbolId": "mixed:GrandChild", - }, - "testpkg.IRetainedInterface": Object { - "assembly": "testpkg", - "fqn": "testpkg.IRetainedInterface", - "kind": "interface", - "locationInModule": Object { - "filename": "retained.ts", - "line": 2, - }, - "name": "IRetainedInterface", - "symbolId": "retained:IRetainedInterface", - }, - "testpkg.Retained": Object { - "abstract": true, - "assembly": "testpkg", - "fqn": "testpkg.Retained", - "initializer": Object {}, - "kind": "class", - "locationInModule": Object { - "filename": "mixed.ts", - "line": 4, - }, - "name": "Retained", - "properties": Array [ - Object { - "docs": Object { - "deprecated": "stripped", - "stability": "deprecated", + "testpkg.GrandChild": Object { + "assembly": "testpkg", + "base": "testpkg.Deprecated", + "fqn": "testpkg.GrandChild", + "initializer": Object {}, + "kind": "class", + "locationInModule": Object { + "filename": "mixed.ts", + "line": 11, + }, + "methods": Array [ + Object { + "locationInModule": Object { + "filename": "mixed.ts", + "line": 12, + }, + "name": "retainedMethod", + }, + ], + "name": "GrandChild", + "symbolId": "mixed:GrandChild", }, - "immutable": true, - "locationInModule": Object { - "filename": "mixed.ts", - "line": 6, + "testpkg.IRetainedInterface": Object { + "assembly": "testpkg", + "fqn": "testpkg.IRetainedInterface", + "kind": "interface", + "locationInModule": Object { + "filename": "retained.ts", + "line": 2, + }, + "name": "IRetainedInterface", + "symbolId": "retained:IRetainedInterface", }, - "name": "deprecated", - "type": Object { - "primitive": "number", + "testpkg.Retained": Object { + "abstract": true, + "assembly": "testpkg", + "fqn": "testpkg.Retained", + "initializer": Object {}, + "kind": "class", + "locationInModule": Object { + "filename": "mixed.ts", + "line": 4, + }, + "name": "Retained", + "properties": Array [ + Object { + "docs": Object { + "deprecated": "stripped", + "stability": "deprecated", + }, + "immutable": true, + "locationInModule": Object { + "filename": "mixed.ts", + "line": 6, + }, + "name": "deprecated", + "type": Object { + "primitive": "number", + }, + }, + Object { + "immutable": true, + "locationInModule": Object { + "filename": "mixed.ts", + "line": 7, + }, + "name": "retained", + "type": Object { + "primitive": "string", + }, + }, + ], + "symbolId": "mixed:Retained", }, - }, - Object { - "immutable": true, - "locationInModule": Object { - "filename": "mixed.ts", - "line": 7, + "testpkg.RetainedClass": Object { + "assembly": "testpkg", + "fqn": "testpkg.RetainedClass", + "initializer": Object {}, + "kind": "class", + "locationInModule": Object { + "filename": "retained.ts", + "line": 3, + }, + "name": "RetainedClass", + "symbolId": "retained:RetainedClass", }, - "name": "retained", - "type": Object { - "primitive": "string", + "testpkg.SomeEnum": Object { + "assembly": "testpkg", + "fqn": "testpkg.SomeEnum", + "kind": "enum", + "locationInModule": Object { + "filename": "enums.ts", + "line": 2, + }, + "members": Array [ + Object { + "name": "VALUE_RETAINED", + }, + ], + "name": "SomeEnum", + "symbolId": "enums:SomeEnum", }, - }, - ], - "symbolId": "mixed:Retained", - }, - "testpkg.RetainedClass": Object { - "assembly": "testpkg", - "fqn": "testpkg.RetainedClass", - "initializer": Object {}, - "kind": "class", - "locationInModule": Object { - "filename": "retained.ts", - "line": 3, - }, - "name": "RetainedClass", - "symbolId": "retained:RetainedClass", - }, - "testpkg.SomeEnum": Object { - "assembly": "testpkg", - "fqn": "testpkg.SomeEnum", - "kind": "enum", - "locationInModule": Object { - "filename": "enums.ts", - "line": 2, - }, - "members": Array [ - Object { - "name": "VALUE_RETAINED", - }, - ], - "name": "SomeEnum", - "symbolId": "enums:SomeEnum", - }, - } - `); + } + `); expect(declFilesSnapshot(result)).toMatchInlineSnapshot(` - "////////////////// - /// index.d.ts /// - export * from './deprecated'; - export * from './retained'; - export * from './enums'; - export { Deprecated, GrandChild, Retained } from './mixed'; - ////////////////// - - - /////////////////////// - /// deprecated.d.ts /// - /** - * @deprecated stripped - */ - export declare class DeprecatedClass { - } - /////////////////////// - - - ///////////////////// - /// retained.d.ts /// - export interface IRetainedInterface { - } - export declare class RetainedClass { - } - ///////////////////// - - - ////////////////// - /// enums.d.ts /// - export declare enum SomeEnum { - VALUE_RETAINED = 0 - } - /** - * @deprecated stripped - */ - export declare enum DeprecatedEnum { - /** - * @deprecated - */ - VALUE_ONE = 0, - /** - * @deprecated - */ - VALUE_TWO = 1 - } - ////////////////// - - - ////////////////// - /// mixed.d.ts /// - import { IRetainedInterface } from './retained'; - export declare abstract class Retained { - /** - * @deprecated stripped - */ - readonly deprecated = 1337; - readonly retained = \\"YEAH\\"; - } - /** - * @deprecated stripped - */ - export declare class Deprecated extends Retained implements IRetainedInterface { - } - export declare class GrandChild extends Deprecated { - retainedMethod(): void; - } - ////////////////// - " - `); + "////////////////// + /// index.d.ts /// + export * from './deprecated'; + export * from './retained'; + export * from './enums'; + export { Deprecated, GrandChild, Retained } from './mixed'; + ////////////////// + + + /////////////////////// + /// deprecated.d.ts /// + /** @deprecated stripped */ + export declare class DeprecatedClass { + } + /////////////////////// + + + ///////////////////// + /// retained.d.ts /// + export interface IRetainedInterface { + } + export declare class RetainedClass { + } + ///////////////////// + + + ////////////////// + /// enums.d.ts /// + export declare enum SomeEnum { + VALUE_RETAINED = 0 + } + /** @deprecated stripped */ + export declare enum DeprecatedEnum { + VALUE_ONE = 0, + VALUE_TWO = 1 + } + ////////////////// + + + ////////////////// + /// mixed.d.ts /// + import { IRetainedInterface } from './retained'; + export declare abstract class Retained { + /** @deprecated stripped */ + readonly deprecated = 1337; + readonly retained = \\"YEAH\\"; + } + /** @deprecated stripped */ + export declare class Deprecated extends Retained implements IRetainedInterface { + } + export declare class GrandChild extends Deprecated { + retainedMethod(): void; + } + ////////////////// + " + `); }); }); diff --git a/packages/jsii/test/docs.test.ts b/packages/jsii/test/docs.test.ts index 07654f4fc7..b772d2c8ff 100644 --- a/packages/jsii/test/docs.test.ts +++ b/packages/jsii/test/docs.test.ts @@ -1,8 +1,7 @@ import * as spec from '@jsii/spec'; import { Stability } from '@jsii/spec'; -import { sourceToAssemblyHelper as compile, compileJsiiForTest } from '../lib'; -import { renderSymbolDocumentation } from '../lib/docs'; +import { sourceToAssemblyHelper as compile } from '../lib'; jest.setTimeout(60_000); @@ -371,125 +370,3 @@ test('@example can contain @ sign', async () => { const classType = assembly.types!['testpkg.Foo'] as spec.ClassType; expect(classType.docs!.example).toBe("import * as x from '@banana';"); }); - -// ---------------------------------------------------------------------- - -test('@experimental status is reflected in generated docstring', async () => { - const result = await compileJsiiForTest(` - /** - * Here is a fresh class - * - * @experimental - */ - export class Foo { - } - `); - - expect(result.files['index.js']).toContain( - lines( - '/**', - ' * (experimental) Here is a fresh class.', - ' *', - ' * @experimental', - ' */', - 'class Foo {', - '}', - ), - ); - - expect(result.files['index.d.ts']).toContain( - lines( - '/**', - ' * (experimental) Here is a fresh class.', - ' *', - ' * @experimental', - ' */', - 'export declare class Foo {', - '}', - ), - ); -}); - -// ---------------------------------------------------------------------- - -test('@deprecated status is reflected in generated docstring', async () => { - const result = await compileJsiiForTest(` - /** - * Here is an old class - * - * @deprecated Use something else - */ - export class Fogey { - } - `); - - expect(result.files['index.js']).toContain( - lines( - '/**', - ' * (deprecated) Here is an old class.', - ' *', - ' * @deprecated Use something else', - ' */', - 'class Fogey {', - '}', - ), - ); - - expect(result.files['index.d.ts']).toContain( - lines( - '/**', - ' * (deprecated) Here is an old class.', - ' *', - ' * @deprecated Use something else', - ' */', - 'export declare class Fogey {', - '}', - ), - ); -}); - -// ---------------------------------------------------------------------- - -test('Rendering jsii docs back to a doc comment', () => { - expect( - renderSymbolDocumentation({ - summary: 'This is the summary', - remarks: 'You can use this\nor not, as you see fit.', - default: 'thas a default value', - see: 'https://some.url/', - subclassable: true, - returns: 'A value', - example: 'print("a thing");', - custom: { - sing: 'whenyourewinning', - }, - }), - ).toEqual( - lines( - 'This is the summary', - '', - 'You can use this', - 'or not, as you see fit.', - '', - '@returns A value', - '@default thas a default value', - '@see https://some.url/', - '@subclassable', - '@sing whenyourewinning', - '@example', - '', - 'print("a thing");', - ), - ); -}); - -// ---------------------------------------------------------------------- - -function lines(...ls: string[]) { - return indented(0, ...ls); -} - -function indented(indent: number, ...lines: string[]) { - const prefix = ' '.repeat(indent); - return lines.map((l) => `${prefix}${l}`).join('\n'); -}