From 87666a9e361bdc2c651d441c32358e0304bfcc81 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 9 Dec 2019 17:03:39 -0800 Subject: [PATCH 01/11] Add @private/@protected/@public test --- tests/cases/conformance/jsdoc/privateTag.ts | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/cases/conformance/jsdoc/privateTag.ts diff --git a/tests/cases/conformance/jsdoc/privateTag.ts b/tests/cases/conformance/jsdoc/privateTag.ts new file mode 100644 index 0000000000000..c66bf9f6e33ea --- /dev/null +++ b/tests/cases/conformance/jsdoc/privateTag.ts @@ -0,0 +1,62 @@ +// @allowJs: true +// @checkJs: true +// @out: foo.js +// @declare: true +// @Filename: privateTag.js + +class A { + /** + * Ap docs + * + * @private + */ + p; + /** + * Aq docs + * + * @protected + */ + q; + /** + * Ar docs + * + * @public + */ + r; +} +class C { + constructor() { + /** + * Cp docs + * + * @private + */ + this.p = 1; + /** + * Cq docs + * + * @protected + */ + this.q = 2; + /** + * Cr docs + * + * @public + */ + this.r = 3; + } +} +class B extends A { + m() { + this.p + this.q + this.r + } +} +class D extends C { + n() { + this.p + this.q + this.r + } +} +new A().p + new A().q + new A().r +new B().p + new B().q + new B().r +new C().p + new C().q + new C().r +new D().p + new D().q + new D().r From 9c1a370fd36dbe5b1673f55ab8750db592f61b69 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 9 Dec 2019 17:06:32 -0800 Subject: [PATCH 02/11] Fix @declaration --- tests/cases/conformance/jsdoc/privateTag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/conformance/jsdoc/privateTag.ts b/tests/cases/conformance/jsdoc/privateTag.ts index c66bf9f6e33ea..6b3781518823e 100644 --- a/tests/cases/conformance/jsdoc/privateTag.ts +++ b/tests/cases/conformance/jsdoc/privateTag.ts @@ -1,7 +1,7 @@ // @allowJs: true // @checkJs: true // @out: foo.js -// @declare: true +// @declaration: true // @Filename: privateTag.js class A { From 88dcb39c4486e254f82e08c1664c3864b1217087 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 9 Dec 2019 17:16:54 -0800 Subject: [PATCH 03/11] draft abstraction + one usage --- src/compiler/checker.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1a5559794be9e..4112f4ec3dec1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6363,6 +6363,15 @@ namespace ts { return name !== undefined ? name : symbolName(symbol); } + function getEffectivePrivacyModifier(node: Node, flags: ModifierFlags) { + Debug.assert((flags & ~(ModifierFlags.Public | ModifierFlags.Private | ModifierFlags.Protected)) === 0); + return hasModifier(node, flags) + || isInJSFile(node) + && (!(flags & ModifierFlags.Public) || getJSDocPublicTag(node)) + && (!(flags & ModifierFlags.Private) || getJSDocPrivateTag(node)) + && (!(flags & ModifierFlags.Protected) || getJSDocProtectedTag(node)); + } + function isDeclarationVisible(node: Node): boolean { if (node) { const links = getNodeLinks(node); @@ -6417,7 +6426,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (hasModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { + if (getEffectivePrivacyModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { // Private/protected properties/methods are not visible return false; } From 871a6433ad4348b07a03b62d294ead7e997b9874 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 10 Dec 2019 07:44:48 -0800 Subject: [PATCH 04/11] Fill in necessary parsing etc --- src/compiler/parser.ts | 18 +++++++++++++++--- src/compiler/types.ts | 15 +++++++++++++++ src/compiler/utilitiesPublic.ts | 29 ++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 0cda1e4d1d8c2..9d50be443250a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -506,6 +506,9 @@ namespace ts { return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode); case SyntaxKind.JSDocTag: case SyntaxKind.JSDocClassTag: + case SyntaxKind.JSDocPrivateTag: + case SyntaxKind.JSDocProtectedTag: + case SyntaxKind.JSDocPublicTag: return visitNode(cbNode, (node as JSDocTag).tagName); case SyntaxKind.PartiallyEmittedExpression: return visitNode(cbNode, (node).expression); @@ -6826,7 +6829,16 @@ namespace ts { break; case "class": case "constructor": - tag = parseClassTag(start, tagName); + tag = parseSimpleTag(start, SyntaxKind.JSDocClassTag, tagName); + break; + case "private": + tag = parseSimpleTag(start, SyntaxKind.JSDocPrivateTag, tagName); + break; + case "protected": + tag = parseSimpleTag(start, SyntaxKind.JSDocProtectedTag, tagName); + break; + case "public": + tag = parseSimpleTag(start, SyntaxKind.JSDocPublicTag, tagName); break; case "this": tag = parseThisTag(start, tagName); @@ -7192,8 +7204,8 @@ namespace ts { return node; } - function parseClassTag(start: number, tagName: Identifier): JSDocClassTag { - const tag = createNode(SyntaxKind.JSDocClassTag, start); + function parseSimpleTag(start: number, kind: SyntaxKind, tagName: Identifier): JSDocTag { + const tag = createNode(kind, start); tag.tagName = tagName; return finishNode(tag); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 76f98537f9b9d..0c3cb29df9aad 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -468,6 +468,9 @@ namespace ts { JSDocAugmentsTag, JSDocAuthorTag, JSDocClassTag, + JSDocPrivateTag, + JSDocProtectedTag, + JSDocPublicTag, JSDocCallbackTag, JSDocEnumTag, JSDocParameterTag, @@ -2610,6 +2613,18 @@ namespace ts { kind: SyntaxKind.JSDocClassTag; } + export interface JSDocPrivateTag extends JSDocTag { + kind: SyntaxKind.JSDocPrivateTag; + } + + export interface JSDocProtectedTag extends JSDocTag { + kind: SyntaxKind.JSDocProtectedTag; + } + + export interface JSDocPublicTag extends JSDocTag { + kind: SyntaxKind.JSDocPublicTag; + } + export interface JSDocEnumTag extends JSDocTag, Declaration { parent: JSDoc; kind: SyntaxKind.JSDocEnumTag; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 9311cb44f3ac4..8a9e4d86c3888 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -673,6 +673,21 @@ namespace ts { return getFirstJSDocTag(node, isJSDocClassTag); } + /** Gets the JSDoc private tag for the node if present */ + export function getJSDocPrivateTag(node: Node): JSDocPrivateTag | undefined { + return getFirstJSDocTag(node, isJSDocPrivateTag); + } + + /** Gets the JSDoc protected tag for the node if present */ + export function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined { + return getFirstJSDocTag(node, isJSDocProtectedTag); + } + + /** Gets the JSDoc public tag for the node if present */ + export function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined { + return getFirstJSDocTag(node, isJSDocPublicTag); + } + /** Gets the JSDoc enum tag for the node if present */ export function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined { return getFirstJSDocTag(node, isJSDocEnumTag); @@ -1547,6 +1562,18 @@ namespace ts { return node.kind === SyntaxKind.JSDocClassTag; } + export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag { + return node.kind === SyntaxKind.JSDocPrivateTag; + } + + export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag { + return node.kind === SyntaxKind.JSDocProtectedTag; + } + + export function isJSDocPublicTag(node: Node): node is JSDocPublicTag { + return node.kind === SyntaxKind.JSDocPublicTag; + } + export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { return node.kind === SyntaxKind.JSDocEnumTag; } @@ -2469,4 +2496,4 @@ namespace ts { } // #endregion -} \ No newline at end of file +} From 455b7b3d769994baf701a2b4c11a877b7018c299 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 13 Dec 2019 13:35:45 -0800 Subject: [PATCH 05/11] make general getEffectiveModifierFlags move to utilities, make the right things call it --- src/compiler/checker.ts | 20 ++++++-------------- src/compiler/transformers/declarations.ts | 2 +- src/compiler/utilities.ts | 13 ++++++++++++- src/compiler/utilitiesPublic.ts | 2 +- tests/cases/conformance/jsdoc/privateTag.ts | 7 ++++--- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4112f4ec3dec1..ed78e6bf0d709 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5322,7 +5322,7 @@ namespace ts { newModifierFlags |= ModifierFlags.Default; } if (newModifierFlags) { - node.modifiers = createNodeArray(createModifiersFromModifierFlags(newModifierFlags | getModifierFlags(node))); + node.modifiers = createNodeArray(createModifiersFromModifierFlags(newModifierFlags | getEffectiveModifierFlags(node))); node.modifierFlagsCache = 0; // Reset computed flags cache } results.push(node); @@ -6363,15 +6363,6 @@ namespace ts { return name !== undefined ? name : symbolName(symbol); } - function getEffectivePrivacyModifier(node: Node, flags: ModifierFlags) { - Debug.assert((flags & ~(ModifierFlags.Public | ModifierFlags.Private | ModifierFlags.Protected)) === 0); - return hasModifier(node, flags) - || isInJSFile(node) - && (!(flags & ModifierFlags.Public) || getJSDocPublicTag(node)) - && (!(flags & ModifierFlags.Private) || getJSDocPrivateTag(node)) - && (!(flags & ModifierFlags.Protected) || getJSDocProtectedTag(node)); - } - function isDeclarationVisible(node: Node): boolean { if (node) { const links = getNodeLinks(node); @@ -6426,7 +6417,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (getEffectivePrivacyModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { + if (getEffectiveModifierFlags(node) & (ModifierFlags.Private | ModifierFlags.Protected)) { // Private/protected properties/methods are not visible return false; } @@ -9760,6 +9751,7 @@ namespace ts { const type = getApparentType(current); if (type !== errorType) { const prop = getPropertyOfType(type, name); + getEffectiveModifierFlags const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0; if (prop && !(modifiers & excludeModifiers)) { if (isUnion) { @@ -28345,9 +28337,9 @@ namespace ts { const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { - const nodeFlags = getModifierFlags(node); - const otherFlags = getModifierFlags(otherAccessor); - if ((nodeFlags & ModifierFlags.AccessibilityModifier) !== (otherFlags & ModifierFlags.AccessibilityModifier)) { + const nodeFlags = getEffectiveModifierFlags(node) & ModifierFlags.AccessibilityModifier; + const otherFlags = getEffectiveModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier; + if (nodeFlags !== otherFlags) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } if ((nodeFlags & ModifierFlags.Abstract) !== (otherFlags & ModifierFlags.Abstract)) { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index e6413af8e85ea..f7116cba735f3 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1476,7 +1476,7 @@ namespace ts { } function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags { - let flags = (getModifierFlags(node) & modifierMask) | modifierAdditions; + let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions; if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) { // A non-exported default is a nonsequitor - we usually try to remove all export modifiers // from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e1256b775dce9..0824724b45349 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4100,7 +4100,7 @@ namespace ts { } export function getSelectedModifierFlags(node: Node, flags: ModifierFlags): ModifierFlags { - return getModifierFlags(node) & flags; + return getEffectiveModifierFlags(node) & flags; } export function getModifierFlags(node: Node): ModifierFlags { @@ -4128,6 +4128,17 @@ namespace ts { return flags; } + export function getEffectiveModifierFlags(node: Node) { + const flags = getModifierFlags(node); + if (isInJSFile(node)) { + const tags = (getJSDocPublicTag(node) ? ModifierFlags.Public : ModifierFlags.None) + | (getJSDocPrivateTag(node) ? ModifierFlags.Private : ModifierFlags.None) + | (getJSDocProtectedTag(node) ? ModifierFlags.Protected : ModifierFlags.None); + return flags | tags; + } + return flags; + } + export function modifierToFlag(token: SyntaxKind): ModifierFlags { switch (token) { case SyntaxKind.StaticKeyword: return ModifierFlags.Static; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 8a9e4d86c3888..bef267734f336 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -299,7 +299,7 @@ namespace ts { } export function getCombinedModifierFlags(node: Declaration): ModifierFlags { - return getCombinedFlags(node, getModifierFlags); + return getCombinedFlags(node, getEffectiveModifierFlags); } // Returns the node flags for this node and all relevant parent nodes. This is done so that diff --git a/tests/cases/conformance/jsdoc/privateTag.ts b/tests/cases/conformance/jsdoc/privateTag.ts index 6b3781518823e..68b0432a476cb 100644 --- a/tests/cases/conformance/jsdoc/privateTag.ts +++ b/tests/cases/conformance/jsdoc/privateTag.ts @@ -4,25 +4,26 @@ // @declaration: true // @Filename: privateTag.js +// TODO: Test get/set that disagree in visibility. class A { /** * Ap docs * * @private */ - p; + p = 4; /** * Aq docs * * @protected */ - q; + q = 5; /** * Ar docs * * @public */ - r; + r = 6; } class C { constructor() { From bd5781ac21b12b05851ba752afcce37d37ce719c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 13 Dec 2019 13:42:07 -0800 Subject: [PATCH 06/11] reorder public/private/protected --- src/compiler/parser.ts | 8 ++++---- src/compiler/types.ts | 10 +++++----- src/compiler/utilitiesPublic.ts | 18 +++++++++--------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9d50be443250a..51ad157072924 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -506,9 +506,9 @@ namespace ts { return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode); case SyntaxKind.JSDocTag: case SyntaxKind.JSDocClassTag: + case SyntaxKind.JSDocPublicTag: case SyntaxKind.JSDocPrivateTag: case SyntaxKind.JSDocProtectedTag: - case SyntaxKind.JSDocPublicTag: return visitNode(cbNode, (node as JSDocTag).tagName); case SyntaxKind.PartiallyEmittedExpression: return visitNode(cbNode, (node).expression); @@ -6831,15 +6831,15 @@ namespace ts { case "constructor": tag = parseSimpleTag(start, SyntaxKind.JSDocClassTag, tagName); break; + case "public": + tag = parseSimpleTag(start, SyntaxKind.JSDocPublicTag, tagName); + break; case "private": tag = parseSimpleTag(start, SyntaxKind.JSDocPrivateTag, tagName); break; case "protected": tag = parseSimpleTag(start, SyntaxKind.JSDocProtectedTag, tagName); break; - case "public": - tag = parseSimpleTag(start, SyntaxKind.JSDocPublicTag, tagName); - break; case "this": tag = parseThisTag(start, tagName); break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0c3cb29df9aad..187f313815019 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -468,9 +468,9 @@ namespace ts { JSDocAugmentsTag, JSDocAuthorTag, JSDocClassTag, + JSDocPublicTag, JSDocPrivateTag, JSDocProtectedTag, - JSDocPublicTag, JSDocCallbackTag, JSDocEnumTag, JSDocParameterTag, @@ -2613,6 +2613,10 @@ namespace ts { kind: SyntaxKind.JSDocClassTag; } + export interface JSDocPublicTag extends JSDocTag { + kind: SyntaxKind.JSDocPublicTag; + } + export interface JSDocPrivateTag extends JSDocTag { kind: SyntaxKind.JSDocPrivateTag; } @@ -2621,10 +2625,6 @@ namespace ts { kind: SyntaxKind.JSDocProtectedTag; } - export interface JSDocPublicTag extends JSDocTag { - kind: SyntaxKind.JSDocPublicTag; - } - export interface JSDocEnumTag extends JSDocTag, Declaration { parent: JSDoc; kind: SyntaxKind.JSDocEnumTag; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index bef267734f336..74685a2d2a4f8 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -673,6 +673,11 @@ namespace ts { return getFirstJSDocTag(node, isJSDocClassTag); } + /** Gets the JSDoc public tag for the node if present */ + export function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined { + return getFirstJSDocTag(node, isJSDocPublicTag); + } + /** Gets the JSDoc private tag for the node if present */ export function getJSDocPrivateTag(node: Node): JSDocPrivateTag | undefined { return getFirstJSDocTag(node, isJSDocPrivateTag); @@ -683,11 +688,6 @@ namespace ts { return getFirstJSDocTag(node, isJSDocProtectedTag); } - /** Gets the JSDoc public tag for the node if present */ - export function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined { - return getFirstJSDocTag(node, isJSDocPublicTag); - } - /** Gets the JSDoc enum tag for the node if present */ export function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined { return getFirstJSDocTag(node, isJSDocEnumTag); @@ -1562,6 +1562,10 @@ namespace ts { return node.kind === SyntaxKind.JSDocClassTag; } + export function isJSDocPublicTag(node: Node): node is JSDocPublicTag { + return node.kind === SyntaxKind.JSDocPublicTag; + } + export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag { return node.kind === SyntaxKind.JSDocPrivateTag; } @@ -1570,10 +1574,6 @@ namespace ts { return node.kind === SyntaxKind.JSDocProtectedTag; } - export function isJSDocPublicTag(node: Node): node is JSDocPublicTag { - return node.kind === SyntaxKind.JSDocPublicTag; - } - export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { return node.kind === SyntaxKind.JSDocEnumTag; } From 14d3c38798534187df0300d334de6bc0acf6d20a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 13 Dec 2019 16:15:55 -0800 Subject: [PATCH 07/11] JS declaration emit works with @public/@private/@protected --- src/compiler/checker.ts | 43 +++- src/compiler/transformers/declarations.ts | 15 +- .../jsdocAccessibilityTags.errors.txt | 117 +++++++++ .../reference/jsdocAccessibilityTags.js | 225 +++++++++++++++++ .../reference/jsdocAccessibilityTags.symbols | 202 +++++++++++++++ .../reference/jsdocAccessibilityTags.types | 237 ++++++++++++++++++ .../jsdoc/jsdocAccessibilityTags.ts | 84 +++++++ tests/cases/conformance/jsdoc/privateTag.ts | 63 ----- 8 files changed, 905 insertions(+), 81 deletions(-) create mode 100644 tests/baselines/reference/jsdocAccessibilityTags.errors.txt create mode 100644 tests/baselines/reference/jsdocAccessibilityTags.js create mode 100644 tests/baselines/reference/jsdocAccessibilityTags.symbols create mode 100644 tests/baselines/reference/jsdocAccessibilityTags.types create mode 100644 tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts delete mode 100644 tests/cases/conformance/jsdoc/privateTag.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed78e6bf0d709..c5062c66cc6ba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5570,6 +5570,7 @@ namespace ts { getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" ), p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType)); + const constructors = serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[]; for (const c of constructors) { // A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration @@ -5833,6 +5834,8 @@ namespace ts { initializer: Expression | undefined ) => T, methodKind: SyntaxKind, useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) { return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined) { + const modifierFlags = getDeclarationModifierFlagsFromSymbol(p); + const isPrivate = !!(modifierFlags & ModifierFlags.Private); if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) { // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols // need to be merged namespace members @@ -5844,7 +5847,7 @@ namespace ts { && isTypeIdenticalTo(getTypeOfSymbol(p), getTypeOfPropertyOfType(baseType, p.escapedName)!))) { return []; } - const staticFlag = isStatic ? ModifierFlags.Static : 0; + const flag = modifierFlags | (isStatic ? ModifierFlags.Static : 0); const name = getPropertyNameNodeForSymbol(p, context); const firstPropertyLikeDecl = find(p.declarations, or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression)); if (p.flags & SymbolFlags.Accessor && useAccessors) { @@ -5852,7 +5855,7 @@ namespace ts { if (p.flags & SymbolFlags.SetAccessor) { result.push(setTextRange(createSetAccessor( /*decorators*/ undefined, - createModifiersFromModifierFlags(staticFlag), + createModifiersFromModifierFlags(flag), name, [createParameter( /*decorators*/ undefined, @@ -5860,18 +5863,19 @@ namespace ts { /*dotDotDotToken*/ undefined, "arg", /*questionToken*/ undefined, - serializeTypeForDeclaration(getTypeOfSymbol(p), p) + isPrivate ? undefined : serializeTypeForDeclaration(getTypeOfSymbol(p), p) )], /*body*/ undefined ), find(p.declarations, isSetAccessor) || firstPropertyLikeDecl)); } if (p.flags & SymbolFlags.GetAccessor) { + const isPrivate = modifierFlags & ModifierFlags.Private; result.push(setTextRange(createGetAccessor( /*decorators*/ undefined, - createModifiersFromModifierFlags(staticFlag), + createModifiersFromModifierFlags(flag), name, [], - serializeTypeForDeclaration(getTypeOfSymbol(p), p), + isPrivate ? undefined : serializeTypeForDeclaration(getTypeOfSymbol(p), p), /*body*/ undefined ), find(p.declarations, isGetAccessor) || firstPropertyLikeDecl)); } @@ -5882,10 +5886,10 @@ namespace ts { else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable)) { return setTextRange(createProperty( /*decorators*/ undefined, - createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | staticFlag), + createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), name, p.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined, - serializeTypeForDeclaration(getTypeOfSymbol(p), p), + isPrivate ? undefined : serializeTypeForDeclaration(getTypeOfSymbol(p), p), // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357 // interface members can't have initializers, however class members _can_ /*initializer*/ undefined @@ -5894,13 +5898,24 @@ namespace ts { if (p.flags & (SymbolFlags.Method | SymbolFlags.Function)) { const type = getTypeOfSymbol(p); const signatures = getSignaturesOfType(type, SignatureKind.Call); + if (flag & ModifierFlags.Private) { + return setTextRange(createProperty( + /*decorators*/ undefined, + createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), + name, + p.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined, + /*type*/ undefined, + /*initializer*/ undefined + ), find(p.declarations, isFunctionLikeDeclaration) || signatures[0] && signatures[0].declaration || p.declarations[0]); + } + const results = []; for (const sig of signatures) { // Each overload becomes a separate method declaration, in order const decl = signatureToSignatureDeclarationHelper(sig, methodKind, context) as MethodDeclaration; decl.name = name; // TODO: Clone - if (staticFlag) { - decl.modifiers = createNodeArray(createModifiersFromModifierFlags(staticFlag)); + if (flag) { + decl.modifiers = createNodeArray(createModifiersFromModifierFlags(flag)); } if (p.flags & SymbolFlags.Optional) { decl.questionToken = createToken(SyntaxKind.QuestionToken); @@ -6088,6 +6103,16 @@ namespace ts { } } } + if (signatures.some(s => s.declaration && getEffectiveModifierFlags(s.declaration) & ModifierFlags.Private)) { + return [setTextRange(createProperty( + /*decorators*/ undefined, + createModifiersFromModifierFlags(ModifierFlags.Private), + "constructor", + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ), signatures[0].declaration)]; + } } const results = []; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index f7116cba735f3..d4ff12f3a40c1 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -840,13 +840,11 @@ namespace ts { ensureType(input, input.type) )); case SyntaxKind.Constructor: { - const isPrivate = hasModifier(input, ModifierFlags.Private); // A constructor declaration may not have a type annotation const ctor = createSignatureDeclaration( SyntaxKind.Constructor, - isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), - // TODO: GH#18217 - isPrivate ? undefined! : updateParamsList(input, input.parameters, ModifierFlags.None), + ensureTypeParams(input, input.typeParameters), + updateParamsList(input, input.parameters, ModifierFlags.None), /*type*/ undefined ); ctor.modifiers = createNodeArray(ensureModifiers(input)); @@ -865,15 +863,14 @@ namespace ts { return cleanup(sig); } case SyntaxKind.GetAccessor: { - const isPrivate = hasModifier(input, ModifierFlags.Private); const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); return cleanup(updateGetAccessor( input, /*decorators*/ undefined, ensureModifiers(input), input.name, - updateAccessorParamsList(input, isPrivate), - !isPrivate ? ensureType(input, accessorType) : undefined, + updateAccessorParamsList(input, hasModifier(input, ModifierFlags.Private)), + ensureType(input, accessorType), /*body*/ undefined)); } case SyntaxKind.SetAccessor: { @@ -892,7 +889,7 @@ namespace ts { ensureModifiers(input), input.name, input.questionToken, - !hasModifier(input, ModifierFlags.Private) ? ensureType(input, input.type) : undefined, + ensureType(input, input.type), ensureNoInitializer(input) )); case SyntaxKind.PropertySignature: @@ -901,7 +898,7 @@ namespace ts { ensureModifiers(input), input.name, input.questionToken, - !hasModifier(input, ModifierFlags.Private) ? ensureType(input, input.type) : undefined, + ensureType(input, input.type), ensureNoInitializer(input) )); case SyntaxKind.MethodSignature: { diff --git a/tests/baselines/reference/jsdocAccessibilityTags.errors.txt b/tests/baselines/reference/jsdocAccessibilityTags.errors.txt new file mode 100644 index 0000000000000..d59ecf0ba2f6a --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTags.errors.txt @@ -0,0 +1,117 @@ +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(21,9): error TS2379: Getter and setter accessors do not agree in visibility. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(23,9): error TS2379: Getter and setter accessors do not agree in visibility. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(50,14): error TS2341: Property 'priv' is private and only accessible within class 'A'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(55,14): error TS2341: Property 'priv2' is private and only accessible within class 'C'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(58,9): error TS2341: Property 'priv' is private and only accessible within class 'A'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(58,24): error TS2445: Property 'prot' is protected and only accessible within class 'A' and its subclasses. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(59,9): error TS2341: Property 'priv' is private and only accessible within class 'A'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(59,24): error TS2445: Property 'prot' is protected and only accessible within class 'A' and its subclasses. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(60,9): error TS2341: Property 'priv2' is private and only accessible within class 'C'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(60,25): error TS2445: Property 'prot2' is protected and only accessible within class 'C' and its subclasses. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(61,9): error TS2341: Property 'priv2' is private and only accessible within class 'C'. +tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(61,25): error TS2445: Property 'prot2' is protected and only accessible within class 'C' and its subclasses. + + +==== tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js (12 errors) ==== + class A { + /** + * Ap docs + * + * @private + */ + priv = 4; + /** + * Aq docs + * + * @protected + */ + prot = 5; + /** + * Ar docs + * + * @public + */ + pub = 6; + /** @public */ + get ack() { return this.priv } + ~~~ +!!! error TS2379: Getter and setter accessors do not agree in visibility. + /** @private */ + set ack(value) { } + ~~~ +!!! error TS2379: Getter and setter accessors do not agree in visibility. + } + class C { + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; + } + h() { return this.priv2 } + } + class B extends A { + m() { + this.priv + this.prot + this.pub + ~~~~ +!!! error TS2341: Property 'priv' is private and only accessible within class 'A'. + } + } + class D extends C { + n() { + this.priv2 + this.prot2 + this.pub2 + ~~~~~ +!!! error TS2341: Property 'priv2' is private and only accessible within class 'C'. + } + } + new A().priv + new A().prot + new A().pub + ~~~~ +!!! error TS2341: Property 'priv' is private and only accessible within class 'A'. + ~~~~ +!!! error TS2445: Property 'prot' is protected and only accessible within class 'A' and its subclasses. + new B().priv + new B().prot + new B().pub + ~~~~ +!!! error TS2341: Property 'priv' is private and only accessible within class 'A'. + ~~~~ +!!! error TS2445: Property 'prot' is protected and only accessible within class 'A' and its subclasses. + new C().priv2 + new C().prot2 + new C().pub2 + ~~~~~ +!!! error TS2341: Property 'priv2' is private and only accessible within class 'C'. + ~~~~~ +!!! error TS2445: Property 'prot2' is protected and only accessible within class 'C' and its subclasses. + new D().priv2 + new D().prot2 + new D().pub2 + ~~~~~ +!!! error TS2341: Property 'priv2' is private and only accessible within class 'C'. + ~~~~~ +!!! error TS2445: Property 'prot2' is protected and only accessible within class 'C' and its subclasses. + + class Privacy { + /** @private */ + constructor(c) { + /** @private */ + this.c = c + } + /** @private */ + m() { + return this.c + } + /** @private */ + get p() { return this.c } + /** @private */ + set p(value) { this.c = value } + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAccessibilityTags.js b/tests/baselines/reference/jsdocAccessibilityTags.js new file mode 100644 index 0000000000000..9b513702c7eff --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTags.js @@ -0,0 +1,225 @@ +//// [jsdocAccessibilityTag.js] +class A { + /** + * Ap docs + * + * @private + */ + priv = 4; + /** + * Aq docs + * + * @protected + */ + prot = 5; + /** + * Ar docs + * + * @public + */ + pub = 6; + /** @public */ + get ack() { return this.priv } + /** @private */ + set ack(value) { } +} +class C { + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; + } + h() { return this.priv2 } +} +class B extends A { + m() { + this.priv + this.prot + this.pub + } +} +class D extends C { + n() { + this.priv2 + this.prot2 + this.pub2 + } +} +new A().priv + new A().prot + new A().pub +new B().priv + new B().prot + new B().pub +new C().priv2 + new C().prot2 + new C().pub2 +new D().priv2 + new D().prot2 + new D().pub2 + +class Privacy { + /** @private */ + constructor(c) { + /** @private */ + this.c = c + } + /** @private */ + m() { + return this.c + } + /** @private */ + get p() { return this.c } + /** @private */ + set p(value) { this.c = value } +} + + +//// [foo.js] +class A { + constructor() { + /** + * Ap docs + * + * @private + */ + this.priv = 4; + /** + * Aq docs + * + * @protected + */ + this.prot = 5; + /** + * Ar docs + * + * @public + */ + this.pub = 6; + } + /** @public */ + get ack() { return this.priv; } + /** @private */ + set ack(value) { } +} +class C { + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; + } + h() { return this.priv2; } +} +class B extends A { + m() { + this.priv + this.prot + this.pub; + } +} +class D extends C { + n() { + this.priv2 + this.prot2 + this.pub2; + } +} +new A().priv + new A().prot + new A().pub; +new B().priv + new B().prot + new B().pub; +new C().priv2 + new C().prot2 + new C().pub2; +new D().priv2 + new D().prot2 + new D().pub2; +class Privacy { + /** @private */ + constructor(c) { + /** @private */ + this.c = c; + } + /** @private */ + m() { + return this.c; + } + /** @private */ + get p() { return this.c; } + /** @private */ + set p(value) { this.c = value; } +} + + +//// [foo.d.ts] +declare class A { + /** + * Ap docs + * + * @private + */ + private priv; + /** + * Aq docs + * + * @protected + */ + protected prot: number; + /** + * Ar docs + * + * @public + */ + public pub: number; + /** @private */ + public set ack(arg: number); + /** @public */ + public get ack(): number; +} +declare class C { + /** + * Cp docs + * + * @private + */ + private priv2; + /** + * Cq docs + * + * @protected + */ + protected prot2: number; + /** + * Cr docs + * + * @public + */ + public pub2: number; + h(): number; +} +declare class B extends A { + m(): void; +} +declare class D extends C { + n(): void; +} +declare class Privacy { + /** @private */ + private constructor; + /** @private */ + private c; + /** @private */ + private m; + /** @private */ + private set p(arg); + /** @private */ + private get p(); +} diff --git a/tests/baselines/reference/jsdocAccessibilityTags.symbols b/tests/baselines/reference/jsdocAccessibilityTags.symbols new file mode 100644 index 0000000000000..1ffb9d287b814 --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTags.symbols @@ -0,0 +1,202 @@ +=== tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js === +class A { +>A : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) + + /** + * Ap docs + * + * @private + */ + priv = 4; +>priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) + + /** + * Aq docs + * + * @protected + */ + prot = 5; +>prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) + + /** + * Ar docs + * + * @public + */ + pub = 6; +>pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) + + /** @public */ + get ack() { return this.priv } +>ack : Symbol(A.ack, Decl(jsdocAccessibilityTag.js, 18, 12), Decl(jsdocAccessibilityTag.js, 20, 34)) +>this.priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>this : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) +>priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) + + /** @private */ + set ack(value) { } +>ack : Symbol(A.ack, Decl(jsdocAccessibilityTag.js, 18, 12), Decl(jsdocAccessibilityTag.js, 20, 34)) +>value : Symbol(value, Decl(jsdocAccessibilityTag.js, 22, 12)) +} +class C { +>C : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) + + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; +>this.priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>this : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) + + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; +>this.prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>this : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) + + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; +>this.pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) +>this : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) + } + h() { return this.priv2 } +>h : Symbol(C.h, Decl(jsdocAccessibilityTag.js, 44, 5)) +>this.priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>this : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +} +class B extends A { +>B : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>A : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) + + m() { +>m : Symbol(B.m, Decl(jsdocAccessibilityTag.js, 47, 19)) + + this.priv + this.prot + this.pub +>this.priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>this : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>this.prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>this : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>this.pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) +>this : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) + } +} +class D extends C { +>D : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>C : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) + + n() { +>n : Symbol(D.n, Decl(jsdocAccessibilityTag.js, 52, 19)) + + this.priv2 + this.prot2 + this.pub2 +>this.priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>this : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>this.prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>this : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>this.pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) +>this : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) + } +} +new A().priv + new A().prot + new A().pub +>new A().priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>A : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) +>priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>new A().prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>A : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) +>prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>new A().pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) +>A : Symbol(A, Decl(jsdocAccessibilityTag.js, 0, 0)) +>pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) + +new B().priv + new B().prot + new B().pub +>new B().priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>B : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>priv : Symbol(A.priv, Decl(jsdocAccessibilityTag.js, 0, 9)) +>new B().prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>B : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>prot : Symbol(A.prot, Decl(jsdocAccessibilityTag.js, 6, 13)) +>new B().pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) +>B : Symbol(B, Decl(jsdocAccessibilityTag.js, 46, 1)) +>pub : Symbol(A.pub, Decl(jsdocAccessibilityTag.js, 12, 13)) + +new C().priv2 + new C().prot2 + new C().pub2 +>new C().priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>C : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>new C().prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>C : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>new C().pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) +>C : Symbol(C, Decl(jsdocAccessibilityTag.js, 23, 1)) +>pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) + +new D().priv2 + new D().prot2 + new D().pub2 +>new D().priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>D : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>priv2 : Symbol(C.priv2, Decl(jsdocAccessibilityTag.js, 25, 19)) +>new D().prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>D : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>prot2 : Symbol(C.prot2, Decl(jsdocAccessibilityTag.js, 31, 23)) +>new D().pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) +>D : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) +>pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) + +class Privacy { +>Privacy : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) + + /** @private */ + constructor(c) { +>c : Symbol(c, Decl(jsdocAccessibilityTag.js, 64, 16)) + + /** @private */ + this.c = c +>this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) +>c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>c : Symbol(c, Decl(jsdocAccessibilityTag.js, 64, 16)) + } + /** @private */ + m() { +>m : Symbol(Privacy.m, Decl(jsdocAccessibilityTag.js, 67, 5)) + + return this.c +>this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) +>c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) + } + /** @private */ + get p() { return this.c } +>p : Symbol(Privacy.p, Decl(jsdocAccessibilityTag.js, 71, 5), Decl(jsdocAccessibilityTag.js, 73, 29)) +>this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) +>c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) + + /** @private */ + set p(value) { this.c = value } +>p : Symbol(Privacy.p, Decl(jsdocAccessibilityTag.js, 71, 5), Decl(jsdocAccessibilityTag.js, 73, 29)) +>value : Symbol(value, Decl(jsdocAccessibilityTag.js, 75, 10)) +>this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) +>c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) +>value : Symbol(value, Decl(jsdocAccessibilityTag.js, 75, 10)) +} + diff --git a/tests/baselines/reference/jsdocAccessibilityTags.types b/tests/baselines/reference/jsdocAccessibilityTags.types new file mode 100644 index 0000000000000..6fbdcaa8eeb02 --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTags.types @@ -0,0 +1,237 @@ +=== tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js === +class A { +>A : A + + /** + * Ap docs + * + * @private + */ + priv = 4; +>priv : number +>4 : 4 + + /** + * Aq docs + * + * @protected + */ + prot = 5; +>prot : number +>5 : 5 + + /** + * Ar docs + * + * @public + */ + pub = 6; +>pub : number +>6 : 6 + + /** @public */ + get ack() { return this.priv } +>ack : number +>this.priv : number +>this : this +>priv : number + + /** @private */ + set ack(value) { } +>ack : number +>value : number +} +class C { +>C : C + + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; +>this.priv2 = 1 : 1 +>this.priv2 : number +>this : this +>priv2 : number +>1 : 1 + + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; +>this.prot2 = 2 : 2 +>this.prot2 : number +>this : this +>prot2 : number +>2 : 2 + + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; +>this.pub2 = 3 : 3 +>this.pub2 : number +>this : this +>pub2 : number +>3 : 3 + } + h() { return this.priv2 } +>h : () => number +>this.priv2 : number +>this : this +>priv2 : number +} +class B extends A { +>B : B +>A : A + + m() { +>m : () => void + + this.priv + this.prot + this.pub +>this.priv + this.prot + this.pub : number +>this.priv + this.prot : number +>this.priv : number +>this : this +>priv : number +>this.prot : number +>this : this +>prot : number +>this.pub : number +>this : this +>pub : number + } +} +class D extends C { +>D : D +>C : C + + n() { +>n : () => void + + this.priv2 + this.prot2 + this.pub2 +>this.priv2 + this.prot2 + this.pub2 : number +>this.priv2 + this.prot2 : number +>this.priv2 : number +>this : this +>priv2 : number +>this.prot2 : number +>this : this +>prot2 : number +>this.pub2 : number +>this : this +>pub2 : number + } +} +new A().priv + new A().prot + new A().pub +>new A().priv + new A().prot + new A().pub : number +>new A().priv + new A().prot : number +>new A().priv : number +>new A() : A +>A : typeof A +>priv : number +>new A().prot : number +>new A() : A +>A : typeof A +>prot : number +>new A().pub : number +>new A() : A +>A : typeof A +>pub : number + +new B().priv + new B().prot + new B().pub +>new B().priv + new B().prot + new B().pub : number +>new B().priv + new B().prot : number +>new B().priv : number +>new B() : B +>B : typeof B +>priv : number +>new B().prot : number +>new B() : B +>B : typeof B +>prot : number +>new B().pub : number +>new B() : B +>B : typeof B +>pub : number + +new C().priv2 + new C().prot2 + new C().pub2 +>new C().priv2 + new C().prot2 + new C().pub2 : number +>new C().priv2 + new C().prot2 : number +>new C().priv2 : number +>new C() : C +>C : typeof C +>priv2 : number +>new C().prot2 : number +>new C() : C +>C : typeof C +>prot2 : number +>new C().pub2 : number +>new C() : C +>C : typeof C +>pub2 : number + +new D().priv2 + new D().prot2 + new D().pub2 +>new D().priv2 + new D().prot2 + new D().pub2 : number +>new D().priv2 + new D().prot2 : number +>new D().priv2 : number +>new D() : D +>D : typeof D +>priv2 : number +>new D().prot2 : number +>new D() : D +>D : typeof D +>prot2 : number +>new D().pub2 : number +>new D() : D +>D : typeof D +>pub2 : number + +class Privacy { +>Privacy : Privacy + + /** @private */ + constructor(c) { +>c : any + + /** @private */ + this.c = c +>this.c = c : any +>this.c : any +>this : this +>c : any +>c : any + } + /** @private */ + m() { +>m : () => any + + return this.c +>this.c : any +>this : this +>c : any + } + /** @private */ + get p() { return this.c } +>p : any +>this.c : any +>this : this +>c : any + + /** @private */ + set p(value) { this.c = value } +>p : any +>value : any +>this.c = value : any +>this.c : any +>this : this +>c : any +>value : any +} + diff --git a/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts b/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts new file mode 100644 index 0000000000000..b9e18501fd314 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts @@ -0,0 +1,84 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @out: foo.js +// @declaration: true +// @Filename: jsdocAccessibilityTag.js + +class A { + /** + * Ap docs + * + * @private + */ + priv = 4; + /** + * Aq docs + * + * @protected + */ + prot = 5; + /** + * Ar docs + * + * @public + */ + pub = 6; + /** @public */ + get ack() { return this.priv } + /** @private */ + set ack(value) { } +} +class C { + constructor() { + /** + * Cp docs + * + * @private + */ + this.priv2 = 1; + /** + * Cq docs + * + * @protected + */ + this.prot2 = 2; + /** + * Cr docs + * + * @public + */ + this.pub2 = 3; + } + h() { return this.priv2 } +} +class B extends A { + m() { + this.priv + this.prot + this.pub + } +} +class D extends C { + n() { + this.priv2 + this.prot2 + this.pub2 + } +} +new A().priv + new A().prot + new A().pub +new B().priv + new B().prot + new B().pub +new C().priv2 + new C().prot2 + new C().pub2 +new D().priv2 + new D().prot2 + new D().pub2 + +class Privacy { + /** @private */ + constructor(c) { + /** @private */ + this.c = c + } + /** @private */ + m() { + return this.c + } + /** @private */ + get p() { return this.c } + /** @private */ + set p(value) { this.c = value } +} diff --git a/tests/cases/conformance/jsdoc/privateTag.ts b/tests/cases/conformance/jsdoc/privateTag.ts deleted file mode 100644 index 68b0432a476cb..0000000000000 --- a/tests/cases/conformance/jsdoc/privateTag.ts +++ /dev/null @@ -1,63 +0,0 @@ -// @allowJs: true -// @checkJs: true -// @out: foo.js -// @declaration: true -// @Filename: privateTag.js - -// TODO: Test get/set that disagree in visibility. -class A { - /** - * Ap docs - * - * @private - */ - p = 4; - /** - * Aq docs - * - * @protected - */ - q = 5; - /** - * Ar docs - * - * @public - */ - r = 6; -} -class C { - constructor() { - /** - * Cp docs - * - * @private - */ - this.p = 1; - /** - * Cq docs - * - * @protected - */ - this.q = 2; - /** - * Cr docs - * - * @public - */ - this.r = 3; - } -} -class B extends A { - m() { - this.p + this.q + this.r - } -} -class D extends C { - n() { - this.p + this.q + this.r - } -} -new A().p + new A().q + new A().r -new B().p + new B().q + new B().r -new C().p + new C().q + new C().r -new D().p + new D().q + new D().r From b80847b26a43aed4126b52efea6a823c9306b9a7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 17 Dec 2019 08:59:15 -0800 Subject: [PATCH 08/11] revert unneeded/incorrect changes --- src/compiler/checker.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c5062c66cc6ba..655c1f0a2e83a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5570,7 +5570,6 @@ namespace ts { getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" ), p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType)); - const constructors = serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[]; for (const c of constructors) { // A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration @@ -6442,7 +6441,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (getEffectiveModifierFlags(node) & (ModifierFlags.Private | ModifierFlags.Protected)) { + if (hasModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { // Private/protected properties/methods are not visible return false; } @@ -9776,7 +9775,6 @@ namespace ts { const type = getApparentType(current); if (type !== errorType) { const prop = getPropertyOfType(type, name); - getEffectiveModifierFlags const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0; if (prop && !(modifiers & excludeModifiers)) { if (isUnion) { @@ -28362,9 +28360,9 @@ namespace ts { const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { - const nodeFlags = getEffectiveModifierFlags(node) & ModifierFlags.AccessibilityModifier; - const otherFlags = getEffectiveModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier; - if (nodeFlags !== otherFlags) { + const nodeFlags = getEffectiveModifierFlags(node); + const otherFlags = getEffectiveModifierFlags(otherAccessor); + if ((nodeFlags & ModifierFlags.AccessibilityModifier) !== (otherFlags & ModifierFlags.AccessibilityModifier)) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } if ((nodeFlags & ModifierFlags.Abstract) !== (otherFlags & ModifierFlags.Abstract)) { From 62a568d58a71b223f4995de97cfd2a927aa4db08 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 17 Dec 2019 10:40:39 -0800 Subject: [PATCH 09/11] Update baselines and skip @public/etc when parsing 1. Update the API baselines with the new functions. 2. Do not check for @public/etc during parsing, because parent pointers aren't set, so non-local tags will be missed; this wrong answer will then be cached. --- src/compiler/utilities.ts | 4 +- .../reference/api/tsserverlibrary.d.ts | 59 +++++++++++++------ tests/baselines/reference/api/typescript.d.ts | 59 +++++++++++++------ 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0824724b45349..353df942649a1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4130,7 +4130,9 @@ namespace ts { export function getEffectiveModifierFlags(node: Node) { const flags = getModifierFlags(node); - if (isInJSFile(node)) { + if (!!node.parent && isInJSFile(node)) { + // Do not try to look for tags during parsing, because parent pointers aren't set and + // non-local tags will incorrectly be missed; this wrong answer will be cached. const tags = (getJSDocPublicTag(node) ? ModifierFlags.Public : ModifierFlags.None) | (getJSDocPrivateTag(node) ? ModifierFlags.Private : ModifierFlags.None) | (getJSDocProtectedTag(node) ? ModifierFlags.Protected : ModifierFlags.None); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 07e5407d7060a..944bd0b2e9167 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -383,23 +383,26 @@ declare namespace ts { JSDocAugmentsTag = 305, JSDocAuthorTag = 306, JSDocClassTag = 307, - JSDocCallbackTag = 308, - JSDocEnumTag = 309, - JSDocParameterTag = 310, - JSDocReturnTag = 311, - JSDocThisTag = 312, - JSDocTypeTag = 313, - JSDocTemplateTag = 314, - JSDocTypedefTag = 315, - JSDocPropertyTag = 316, - SyntaxList = 317, - NotEmittedStatement = 318, - PartiallyEmittedExpression = 319, - CommaListExpression = 320, - MergeDeclarationMarker = 321, - EndOfDeclarationMarker = 322, - SyntheticReferenceExpression = 323, - Count = 324, + JSDocPublicTag = 308, + JSDocPrivateTag = 309, + JSDocProtectedTag = 310, + JSDocCallbackTag = 311, + JSDocEnumTag = 312, + JSDocParameterTag = 313, + JSDocReturnTag = 314, + JSDocThisTag = 315, + JSDocTypeTag = 316, + JSDocTemplateTag = 317, + JSDocTypedefTag = 318, + JSDocPropertyTag = 319, + SyntaxList = 320, + NotEmittedStatement = 321, + PartiallyEmittedExpression = 322, + CommaListExpression = 323, + MergeDeclarationMarker = 324, + EndOfDeclarationMarker = 325, + SyntheticReferenceExpression = 326, + Count = 327, FirstAssignment = 62, LastAssignment = 74, FirstCompoundAssignment = 63, @@ -428,9 +431,9 @@ declare namespace ts { LastStatement = 240, FirstNode = 152, FirstJSDocNode = 292, - LastJSDocNode = 316, + LastJSDocNode = 319, FirstJSDocTagNode = 304, - LastJSDocTagNode = 316, + LastJSDocTagNode = 319, } export enum NodeFlags { None = 0, @@ -1619,6 +1622,15 @@ declare namespace ts { export interface JSDocClassTag extends JSDocTag { kind: SyntaxKind.JSDocClassTag; } + export interface JSDocPublicTag extends JSDocTag { + kind: SyntaxKind.JSDocPublicTag; + } + export interface JSDocPrivateTag extends JSDocTag { + kind: SyntaxKind.JSDocPrivateTag; + } + export interface JSDocProtectedTag extends JSDocTag { + kind: SyntaxKind.JSDocProtectedTag; + } export interface JSDocEnumTag extends JSDocTag, Declaration { parent: JSDoc; kind: SyntaxKind.JSDocEnumTag; @@ -3426,6 +3438,12 @@ declare namespace ts { function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined; /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node: Node): JSDocClassTag | undefined; + /** Gets the JSDoc public tag for the node if present */ + function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined; + /** Gets the JSDoc private tag for the node if present */ + function getJSDocPrivateTag(node: Node): JSDocPrivateTag | undefined; + /** Gets the JSDoc protected tag for the node if present */ + function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc enum tag for the node if present */ function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined; /** Gets the JSDoc this tag for the node if present */ @@ -3630,6 +3648,9 @@ declare namespace ts { function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; + function isJSDocPublicTag(node: Node): node is JSDocPublicTag; + function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag; + function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocParameterTag(node: Node): node is JSDocParameterTag; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 5cec6985aa46c..f91dc4b7039c5 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -383,23 +383,26 @@ declare namespace ts { JSDocAugmentsTag = 305, JSDocAuthorTag = 306, JSDocClassTag = 307, - JSDocCallbackTag = 308, - JSDocEnumTag = 309, - JSDocParameterTag = 310, - JSDocReturnTag = 311, - JSDocThisTag = 312, - JSDocTypeTag = 313, - JSDocTemplateTag = 314, - JSDocTypedefTag = 315, - JSDocPropertyTag = 316, - SyntaxList = 317, - NotEmittedStatement = 318, - PartiallyEmittedExpression = 319, - CommaListExpression = 320, - MergeDeclarationMarker = 321, - EndOfDeclarationMarker = 322, - SyntheticReferenceExpression = 323, - Count = 324, + JSDocPublicTag = 308, + JSDocPrivateTag = 309, + JSDocProtectedTag = 310, + JSDocCallbackTag = 311, + JSDocEnumTag = 312, + JSDocParameterTag = 313, + JSDocReturnTag = 314, + JSDocThisTag = 315, + JSDocTypeTag = 316, + JSDocTemplateTag = 317, + JSDocTypedefTag = 318, + JSDocPropertyTag = 319, + SyntaxList = 320, + NotEmittedStatement = 321, + PartiallyEmittedExpression = 322, + CommaListExpression = 323, + MergeDeclarationMarker = 324, + EndOfDeclarationMarker = 325, + SyntheticReferenceExpression = 326, + Count = 327, FirstAssignment = 62, LastAssignment = 74, FirstCompoundAssignment = 63, @@ -428,9 +431,9 @@ declare namespace ts { LastStatement = 240, FirstNode = 152, FirstJSDocNode = 292, - LastJSDocNode = 316, + LastJSDocNode = 319, FirstJSDocTagNode = 304, - LastJSDocTagNode = 316, + LastJSDocTagNode = 319, } export enum NodeFlags { None = 0, @@ -1619,6 +1622,15 @@ declare namespace ts { export interface JSDocClassTag extends JSDocTag { kind: SyntaxKind.JSDocClassTag; } + export interface JSDocPublicTag extends JSDocTag { + kind: SyntaxKind.JSDocPublicTag; + } + export interface JSDocPrivateTag extends JSDocTag { + kind: SyntaxKind.JSDocPrivateTag; + } + export interface JSDocProtectedTag extends JSDocTag { + kind: SyntaxKind.JSDocProtectedTag; + } export interface JSDocEnumTag extends JSDocTag, Declaration { parent: JSDoc; kind: SyntaxKind.JSDocEnumTag; @@ -3426,6 +3438,12 @@ declare namespace ts { function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined; /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node: Node): JSDocClassTag | undefined; + /** Gets the JSDoc public tag for the node if present */ + function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined; + /** Gets the JSDoc private tag for the node if present */ + function getJSDocPrivateTag(node: Node): JSDocPrivateTag | undefined; + /** Gets the JSDoc protected tag for the node if present */ + function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc enum tag for the node if present */ function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined; /** Gets the JSDoc this tag for the node if present */ @@ -3630,6 +3648,9 @@ declare namespace ts { function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; + function isJSDocPublicTag(node: Node): node is JSDocPublicTag; + function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag; + function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocParameterTag(node: Node): node is JSDocParameterTag; From f30f399e18212c0cac87a2171b4074787da720c8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 17 Dec 2019 15:01:51 -0800 Subject: [PATCH 10/11] Parser: don't call hasModifier(s) anymore. Then move jsdoc modifier tag checks into getModifierFlagsNoCache where they should be. The jsdoc checks are skipped when the parent is undefined. There are 3 cases when this can happen: 1. The code is in the parser (or a few places in the binder, notably declareSymbol of module.exports assignments). 2. The node is a source file. 3. The node is synthetic, which I assume to be from the transforms. It is fine to call getModifierFlags in cases (2) and (3). It is not fine for (1), so I removed these calls and replaced them with simple iteration over the modifiers. Worth noting: Ron's uniform node construction PR removes these calls anyway; this PR just does it early. --- src/compiler/checker.ts | 8 ++++---- src/compiler/parser.ts | 21 ++++++++++++-------- src/compiler/transformers/declarations.ts | 2 +- src/compiler/utilities.ts | 24 ++++++++++------------- src/compiler/utilitiesPublic.ts | 2 +- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 655c1f0a2e83a..87668a755a572 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5322,7 +5322,7 @@ namespace ts { newModifierFlags |= ModifierFlags.Default; } if (newModifierFlags) { - node.modifiers = createNodeArray(createModifiersFromModifierFlags(newModifierFlags | getEffectiveModifierFlags(node))); + node.modifiers = createNodeArray(createModifiersFromModifierFlags(newModifierFlags | getModifierFlags(node))); node.modifierFlagsCache = 0; // Reset computed flags cache } results.push(node); @@ -6102,7 +6102,7 @@ namespace ts { } } } - if (signatures.some(s => s.declaration && getEffectiveModifierFlags(s.declaration) & ModifierFlags.Private)) { + if (signatures.some(s => s.declaration && getModifierFlags(s.declaration) & ModifierFlags.Private)) { return [setTextRange(createProperty( /*decorators*/ undefined, createModifiersFromModifierFlags(ModifierFlags.Private), @@ -28360,8 +28360,8 @@ namespace ts { const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { - const nodeFlags = getEffectiveModifierFlags(node); - const otherFlags = getEffectiveModifierFlags(otherAccessor); + const nodeFlags = getModifierFlags(node); + const otherFlags = getModifierFlags(otherAccessor); if ((nodeFlags & ModifierFlags.AccessibilityModifier) !== (otherFlags & ModifierFlags.AccessibilityModifier)) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 51ad157072924..6e4e168e2ca77 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2584,7 +2584,7 @@ namespace ts { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && !hasModifiers(node) && isModifierKind(token())) { + if (getFullWidth(node.name) === 0 && !node.modifiers && isModifierKind(token())) { // in cases like // 'use strict' // function foo(static) @@ -3603,7 +3603,7 @@ namespace ts { return undefined; } - const isAsync = hasModifier(arrowFunction, ModifierFlags.Async); + const isAsync = hasModifierOfKind(arrowFunction, SyntaxKind.AsyncKeyword); // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. @@ -3809,7 +3809,7 @@ namespace ts { function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction | undefined { const node = createNodeWithJSDoc(SyntaxKind.ArrowFunction); node.modifiers = parseModifiersForArrowFunction(); - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = hasModifierOfKind(node, SyntaxKind.AsyncKeyword) ? SignatureFlags.Await : SignatureFlags.None; // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -5005,7 +5005,7 @@ namespace ts { node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = hasModifierOfKind(node, SyntaxKind.AsyncKeyword) ? SignatureFlags.Await : SignatureFlags.None; node.name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : @@ -5834,9 +5834,9 @@ namespace ts { node.kind = SyntaxKind.FunctionDeclaration; parseExpected(SyntaxKind.FunctionKeyword); node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); - node.name = hasModifier(node, ModifierFlags.Default) ? parseOptionalIdentifier() : parseIdentifier(); + node.name = hasModifierOfKind(node, SyntaxKind.DefaultKeyword) ? parseOptionalIdentifier() : parseIdentifier(); const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = hasModifierOfKind(node, SyntaxKind.AsyncKeyword) ? SignatureFlags.Await : SignatureFlags.None; fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected); return finishNode(node); @@ -5869,7 +5869,7 @@ namespace ts { node.kind = SyntaxKind.MethodDeclaration; node.asteriskToken = asteriskToken; const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = hasModifierOfKind(node, SyntaxKind.AsyncKeyword) ? SignatureFlags.Await : SignatureFlags.None; fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); return finishNode(node); @@ -6511,7 +6511,7 @@ namespace ts { } function isAnExternalModuleIndicatorNode(node: Node) { - return hasModifier(node, ModifierFlags.Export) + return hasModifierOfKind(node, SyntaxKind.ExportKeyword) || node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference || node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ExportAssignment @@ -6528,6 +6528,11 @@ namespace ts { return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); } + /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */ + function hasModifierOfKind(node: Node, kind: SyntaxKind) { + return some(node.modifiers, m => m.kind === kind); + } + function isImportMeta(node: Node): boolean { return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index d4ff12f3a40c1..460eb64563898 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1473,7 +1473,7 @@ namespace ts { } function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags { - let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions; + let flags = (getModifierFlags(node) & modifierMask) | modifierAdditions; if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) { // A non-exported default is a nonsequitor - we usually try to remove all export modifiers // from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 353df942649a1..f7e12bd290f0e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4100,7 +4100,7 @@ namespace ts { } export function getSelectedModifierFlags(node: Node, flags: ModifierFlags): ModifierFlags { - return getEffectiveModifierFlags(node) & flags; + return getModifierFlags(node) & flags; } export function getModifierFlags(node: Node): ModifierFlags { @@ -4121,23 +4121,19 @@ namespace ts { } } - if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (node).isInJSDocNamespace)) { - flags |= ModifierFlags.Export; - } - - return flags; - } - - export function getEffectiveModifierFlags(node: Node) { - const flags = getModifierFlags(node); - if (!!node.parent && isInJSFile(node)) { - // Do not try to look for tags during parsing, because parent pointers aren't set and - // non-local tags will incorrectly be missed; this wrong answer will be cached. + if (isInJSFile(node) && !!node.parent) { + // getModifierFlagsNoCache should only be called when parent pointers are set, + // or when !(node.flags & NodeFlags.Synthesized) && node.kind !== SyntaxKind.SourceFile) const tags = (getJSDocPublicTag(node) ? ModifierFlags.Public : ModifierFlags.None) | (getJSDocPrivateTag(node) ? ModifierFlags.Private : ModifierFlags.None) | (getJSDocProtectedTag(node) ? ModifierFlags.Protected : ModifierFlags.None); - return flags | tags; + flags |= tags; + } + + if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (node).isInJSDocNamespace)) { + flags |= ModifierFlags.Export; } + return flags; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 74685a2d2a4f8..4f27c261938c3 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -299,7 +299,7 @@ namespace ts { } export function getCombinedModifierFlags(node: Declaration): ModifierFlags { - return getCombinedFlags(node, getEffectiveModifierFlags); + return getCombinedFlags(node, getModifierFlags); } // Returns the node flags for this node and all relevant parent nodes. This is done so that From 8182bfd6f1f5b198c0c7453e59b296b64af4dd2c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 18 Dec 2019 08:49:41 -0800 Subject: [PATCH 11/11] Fix constructor emit 1. Emit protected for protected, which I missed earlier. 2. Emit a constructor, not a property named "constructor". 3. Split declaration emit tests out so that errors are properly reported there. --- src/compiler/checker.ts | 18 +- .../jsdocAccessibilityTags.errors.txt | 16 -- .../reference/jsdocAccessibilityTags.js | 225 ------------------ .../reference/jsdocAccessibilityTags.symbols | 40 ---- .../reference/jsdocAccessibilityTags.types | 42 ---- .../jsdocAccessibilityTagsDeclarations.js | 92 +++++++ ...jsdocAccessibilityTagsDeclarations.symbols | 81 +++++++ .../jsdocAccessibilityTagsDeclarations.types | 85 +++++++ .../jsdoc/jsdocAccessibilityTags.ts | 19 +- .../jsdocAccessibilityTagsDeclarations.ts | 37 +++ 10 files changed, 307 insertions(+), 348 deletions(-) delete mode 100644 tests/baselines/reference/jsdocAccessibilityTags.js create mode 100644 tests/baselines/reference/jsdocAccessibilityTagsDeclarations.js create mode 100644 tests/baselines/reference/jsdocAccessibilityTagsDeclarations.symbols create mode 100644 tests/baselines/reference/jsdocAccessibilityTagsDeclarations.types create mode 100644 tests/cases/conformance/jsdoc/jsdocAccessibilityTagsDeclarations.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dd4243e771205..4095b0b4b5c7a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6107,14 +6107,18 @@ namespace ts { } } } - if (signatures.some(s => s.declaration && getModifierFlags(s.declaration) & ModifierFlags.Private)) { - return [setTextRange(createProperty( + let privateProtected: ModifierFlags = 0; + for (const s of signatures) { + if (s.declaration) { + privateProtected |= getSelectedModifierFlags(s.declaration, ModifierFlags.Private | ModifierFlags.Protected); + } + } + if (privateProtected) { + return [setTextRange(createConstructor( /*decorators*/ undefined, - createModifiersFromModifierFlags(ModifierFlags.Private), - "constructor", - /*questionOrExclamationToken*/ undefined, - /*type*/ undefined, - /*initializer*/ undefined + createModifiersFromModifierFlags(privateProtected), + /*parameters*/ [], + /*body*/ undefined, ), signatures[0].declaration)]; } } diff --git a/tests/baselines/reference/jsdocAccessibilityTags.errors.txt b/tests/baselines/reference/jsdocAccessibilityTags.errors.txt index d59ecf0ba2f6a..bcbad8b95eaf2 100644 --- a/tests/baselines/reference/jsdocAccessibilityTags.errors.txt +++ b/tests/baselines/reference/jsdocAccessibilityTags.errors.txt @@ -98,20 +98,4 @@ tests/cases/conformance/jsdoc/jsdocAccessibilityTag.js(61,25): error TS2445: Pro !!! error TS2341: Property 'priv2' is private and only accessible within class 'C'. ~~~~~ !!! error TS2445: Property 'prot2' is protected and only accessible within class 'C' and its subclasses. - - class Privacy { - /** @private */ - constructor(c) { - /** @private */ - this.c = c - } - /** @private */ - m() { - return this.c - } - /** @private */ - get p() { return this.c } - /** @private */ - set p(value) { this.c = value } - } \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAccessibilityTags.js b/tests/baselines/reference/jsdocAccessibilityTags.js deleted file mode 100644 index 9b513702c7eff..0000000000000 --- a/tests/baselines/reference/jsdocAccessibilityTags.js +++ /dev/null @@ -1,225 +0,0 @@ -//// [jsdocAccessibilityTag.js] -class A { - /** - * Ap docs - * - * @private - */ - priv = 4; - /** - * Aq docs - * - * @protected - */ - prot = 5; - /** - * Ar docs - * - * @public - */ - pub = 6; - /** @public */ - get ack() { return this.priv } - /** @private */ - set ack(value) { } -} -class C { - constructor() { - /** - * Cp docs - * - * @private - */ - this.priv2 = 1; - /** - * Cq docs - * - * @protected - */ - this.prot2 = 2; - /** - * Cr docs - * - * @public - */ - this.pub2 = 3; - } - h() { return this.priv2 } -} -class B extends A { - m() { - this.priv + this.prot + this.pub - } -} -class D extends C { - n() { - this.priv2 + this.prot2 + this.pub2 - } -} -new A().priv + new A().prot + new A().pub -new B().priv + new B().prot + new B().pub -new C().priv2 + new C().prot2 + new C().pub2 -new D().priv2 + new D().prot2 + new D().pub2 - -class Privacy { - /** @private */ - constructor(c) { - /** @private */ - this.c = c - } - /** @private */ - m() { - return this.c - } - /** @private */ - get p() { return this.c } - /** @private */ - set p(value) { this.c = value } -} - - -//// [foo.js] -class A { - constructor() { - /** - * Ap docs - * - * @private - */ - this.priv = 4; - /** - * Aq docs - * - * @protected - */ - this.prot = 5; - /** - * Ar docs - * - * @public - */ - this.pub = 6; - } - /** @public */ - get ack() { return this.priv; } - /** @private */ - set ack(value) { } -} -class C { - constructor() { - /** - * Cp docs - * - * @private - */ - this.priv2 = 1; - /** - * Cq docs - * - * @protected - */ - this.prot2 = 2; - /** - * Cr docs - * - * @public - */ - this.pub2 = 3; - } - h() { return this.priv2; } -} -class B extends A { - m() { - this.priv + this.prot + this.pub; - } -} -class D extends C { - n() { - this.priv2 + this.prot2 + this.pub2; - } -} -new A().priv + new A().prot + new A().pub; -new B().priv + new B().prot + new B().pub; -new C().priv2 + new C().prot2 + new C().pub2; -new D().priv2 + new D().prot2 + new D().pub2; -class Privacy { - /** @private */ - constructor(c) { - /** @private */ - this.c = c; - } - /** @private */ - m() { - return this.c; - } - /** @private */ - get p() { return this.c; } - /** @private */ - set p(value) { this.c = value; } -} - - -//// [foo.d.ts] -declare class A { - /** - * Ap docs - * - * @private - */ - private priv; - /** - * Aq docs - * - * @protected - */ - protected prot: number; - /** - * Ar docs - * - * @public - */ - public pub: number; - /** @private */ - public set ack(arg: number); - /** @public */ - public get ack(): number; -} -declare class C { - /** - * Cp docs - * - * @private - */ - private priv2; - /** - * Cq docs - * - * @protected - */ - protected prot2: number; - /** - * Cr docs - * - * @public - */ - public pub2: number; - h(): number; -} -declare class B extends A { - m(): void; -} -declare class D extends C { - n(): void; -} -declare class Privacy { - /** @private */ - private constructor; - /** @private */ - private c; - /** @private */ - private m; - /** @private */ - private set p(arg); - /** @private */ - private get p(); -} diff --git a/tests/baselines/reference/jsdocAccessibilityTags.symbols b/tests/baselines/reference/jsdocAccessibilityTags.symbols index 1ffb9d287b814..62f97b37a2e73 100644 --- a/tests/baselines/reference/jsdocAccessibilityTags.symbols +++ b/tests/baselines/reference/jsdocAccessibilityTags.symbols @@ -160,43 +160,3 @@ new D().priv2 + new D().prot2 + new D().pub2 >D : Symbol(D, Decl(jsdocAccessibilityTag.js, 51, 1)) >pub2 : Symbol(C.pub2, Decl(jsdocAccessibilityTag.js, 37, 23)) -class Privacy { ->Privacy : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) - - /** @private */ - constructor(c) { ->c : Symbol(c, Decl(jsdocAccessibilityTag.js, 64, 16)) - - /** @private */ - this.c = c ->this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) ->c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->c : Symbol(c, Decl(jsdocAccessibilityTag.js, 64, 16)) - } - /** @private */ - m() { ->m : Symbol(Privacy.m, Decl(jsdocAccessibilityTag.js, 67, 5)) - - return this.c ->this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) ->c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) - } - /** @private */ - get p() { return this.c } ->p : Symbol(Privacy.p, Decl(jsdocAccessibilityTag.js, 71, 5), Decl(jsdocAccessibilityTag.js, 73, 29)) ->this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) ->c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) - - /** @private */ - set p(value) { this.c = value } ->p : Symbol(Privacy.p, Decl(jsdocAccessibilityTag.js, 71, 5), Decl(jsdocAccessibilityTag.js, 73, 29)) ->value : Symbol(value, Decl(jsdocAccessibilityTag.js, 75, 10)) ->this.c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->this : Symbol(Privacy, Decl(jsdocAccessibilityTag.js, 60, 44)) ->c : Symbol(Privacy.c, Decl(jsdocAccessibilityTag.js, 64, 20), Decl(jsdocAccessibilityTag.js, 75, 18)) ->value : Symbol(value, Decl(jsdocAccessibilityTag.js, 75, 10)) -} - diff --git a/tests/baselines/reference/jsdocAccessibilityTags.types b/tests/baselines/reference/jsdocAccessibilityTags.types index 6fbdcaa8eeb02..18a364c4da843 100644 --- a/tests/baselines/reference/jsdocAccessibilityTags.types +++ b/tests/baselines/reference/jsdocAccessibilityTags.types @@ -193,45 +193,3 @@ new D().priv2 + new D().prot2 + new D().pub2 >D : typeof D >pub2 : number -class Privacy { ->Privacy : Privacy - - /** @private */ - constructor(c) { ->c : any - - /** @private */ - this.c = c ->this.c = c : any ->this.c : any ->this : this ->c : any ->c : any - } - /** @private */ - m() { ->m : () => any - - return this.c ->this.c : any ->this : this ->c : any - } - /** @private */ - get p() { return this.c } ->p : any ->this.c : any ->this : this ->c : any - - /** @private */ - set p(value) { this.c = value } ->p : any ->value : any ->this.c = value : any ->this.c : any ->this : this ->c : any ->value : any -} - diff --git a/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.js b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.js new file mode 100644 index 0000000000000..18031abf9cafc --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.js @@ -0,0 +1,92 @@ +//// [jsdocAccessibilityTagDeclarations.js] +class Protected { + /** @protected */ + constructor(c) { + /** @protected */ + this.c = c + } + /** @protected */ + m() { + return this.c + } + /** @protected */ + get p() { return this.c } + /** @protected */ + set p(value) { this.c = value } +} + +class Private { + /** @private */ + constructor(c) { + /** @private */ + this.c = c + } + /** @private */ + m() { + return this.c + } + /** @private */ + get p() { return this.c } + /** @private */ + set p(value) { this.c = value } +} + + +//// [foo.js] +class Protected { + /** @protected */ + constructor(c) { + /** @protected */ + this.c = c; + } + /** @protected */ + m() { + return this.c; + } + /** @protected */ + get p() { return this.c; } + /** @protected */ + set p(value) { this.c = value; } +} +class Private { + /** @private */ + constructor(c) { + /** @private */ + this.c = c; + } + /** @private */ + m() { + return this.c; + } + /** @private */ + get p() { return this.c; } + /** @private */ + set p(value) { this.c = value; } +} + + +//// [foo.d.ts] +declare class Protected { + /** @protected */ + protected constructor(); + /** @protected */ + protected c: any; + /** @protected */ + protected m(): any; + /** @protected */ + protected set p(arg: any); + /** @protected */ + protected get p(): any; +} +declare class Private { + /** @private */ + private constructor(); + /** @private */ + private c; + /** @private */ + private m; + /** @private */ + private set p(arg); + /** @private */ + private get p(); +} diff --git a/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.symbols b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.symbols new file mode 100644 index 0000000000000..0316e157d31fa --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.symbols @@ -0,0 +1,81 @@ +=== tests/cases/conformance/jsdoc/jsdocAccessibilityTagDeclarations.js === +class Protected { +>Protected : Symbol(Protected, Decl(jsdocAccessibilityTagDeclarations.js, 0, 0)) + + /** @protected */ + constructor(c) { +>c : Symbol(c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 16)) + + /** @protected */ + this.c = c +>this.c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>this : Symbol(Protected, Decl(jsdocAccessibilityTagDeclarations.js, 0, 0)) +>c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>c : Symbol(c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 16)) + } + /** @protected */ + m() { +>m : Symbol(Protected.m, Decl(jsdocAccessibilityTagDeclarations.js, 5, 5)) + + return this.c +>this.c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>this : Symbol(Protected, Decl(jsdocAccessibilityTagDeclarations.js, 0, 0)) +>c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) + } + /** @protected */ + get p() { return this.c } +>p : Symbol(Protected.p, Decl(jsdocAccessibilityTagDeclarations.js, 9, 5), Decl(jsdocAccessibilityTagDeclarations.js, 11, 29)) +>this.c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>this : Symbol(Protected, Decl(jsdocAccessibilityTagDeclarations.js, 0, 0)) +>c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) + + /** @protected */ + set p(value) { this.c = value } +>p : Symbol(Protected.p, Decl(jsdocAccessibilityTagDeclarations.js, 9, 5), Decl(jsdocAccessibilityTagDeclarations.js, 11, 29)) +>value : Symbol(value, Decl(jsdocAccessibilityTagDeclarations.js, 13, 10)) +>this.c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>this : Symbol(Protected, Decl(jsdocAccessibilityTagDeclarations.js, 0, 0)) +>c : Symbol(Protected.c, Decl(jsdocAccessibilityTagDeclarations.js, 2, 20), Decl(jsdocAccessibilityTagDeclarations.js, 13, 18)) +>value : Symbol(value, Decl(jsdocAccessibilityTagDeclarations.js, 13, 10)) +} + +class Private { +>Private : Symbol(Private, Decl(jsdocAccessibilityTagDeclarations.js, 14, 1)) + + /** @private */ + constructor(c) { +>c : Symbol(c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 16)) + + /** @private */ + this.c = c +>this.c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>this : Symbol(Private, Decl(jsdocAccessibilityTagDeclarations.js, 14, 1)) +>c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>c : Symbol(c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 16)) + } + /** @private */ + m() { +>m : Symbol(Private.m, Decl(jsdocAccessibilityTagDeclarations.js, 21, 5)) + + return this.c +>this.c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>this : Symbol(Private, Decl(jsdocAccessibilityTagDeclarations.js, 14, 1)) +>c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) + } + /** @private */ + get p() { return this.c } +>p : Symbol(Private.p, Decl(jsdocAccessibilityTagDeclarations.js, 25, 5), Decl(jsdocAccessibilityTagDeclarations.js, 27, 29)) +>this.c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>this : Symbol(Private, Decl(jsdocAccessibilityTagDeclarations.js, 14, 1)) +>c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) + + /** @private */ + set p(value) { this.c = value } +>p : Symbol(Private.p, Decl(jsdocAccessibilityTagDeclarations.js, 25, 5), Decl(jsdocAccessibilityTagDeclarations.js, 27, 29)) +>value : Symbol(value, Decl(jsdocAccessibilityTagDeclarations.js, 29, 10)) +>this.c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>this : Symbol(Private, Decl(jsdocAccessibilityTagDeclarations.js, 14, 1)) +>c : Symbol(Private.c, Decl(jsdocAccessibilityTagDeclarations.js, 18, 20), Decl(jsdocAccessibilityTagDeclarations.js, 29, 18)) +>value : Symbol(value, Decl(jsdocAccessibilityTagDeclarations.js, 29, 10)) +} + diff --git a/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.types b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.types new file mode 100644 index 0000000000000..88c6acd855d4e --- /dev/null +++ b/tests/baselines/reference/jsdocAccessibilityTagsDeclarations.types @@ -0,0 +1,85 @@ +=== tests/cases/conformance/jsdoc/jsdocAccessibilityTagDeclarations.js === +class Protected { +>Protected : Protected + + /** @protected */ + constructor(c) { +>c : any + + /** @protected */ + this.c = c +>this.c = c : any +>this.c : any +>this : this +>c : any +>c : any + } + /** @protected */ + m() { +>m : () => any + + return this.c +>this.c : any +>this : this +>c : any + } + /** @protected */ + get p() { return this.c } +>p : any +>this.c : any +>this : this +>c : any + + /** @protected */ + set p(value) { this.c = value } +>p : any +>value : any +>this.c = value : any +>this.c : any +>this : this +>c : any +>value : any +} + +class Private { +>Private : Private + + /** @private */ + constructor(c) { +>c : any + + /** @private */ + this.c = c +>this.c = c : any +>this.c : any +>this : this +>c : any +>c : any + } + /** @private */ + m() { +>m : () => any + + return this.c +>this.c : any +>this : this +>c : any + } + /** @private */ + get p() { return this.c } +>p : any +>this.c : any +>this : this +>c : any + + /** @private */ + set p(value) { this.c = value } +>p : any +>value : any +>this.c = value : any +>this.c : any +>this : this +>c : any +>value : any +} + diff --git a/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts b/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts index b9e18501fd314..b32944e8f87aa 100644 --- a/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts +++ b/tests/cases/conformance/jsdoc/jsdocAccessibilityTags.ts @@ -1,8 +1,7 @@ // @allowJs: true // @checkJs: true // @target: esnext -// @out: foo.js -// @declaration: true +// @noEmit: true // @Filename: jsdocAccessibilityTag.js class A { @@ -66,19 +65,3 @@ new A().priv + new A().prot + new A().pub new B().priv + new B().prot + new B().pub new C().priv2 + new C().prot2 + new C().pub2 new D().priv2 + new D().prot2 + new D().pub2 - -class Privacy { - /** @private */ - constructor(c) { - /** @private */ - this.c = c - } - /** @private */ - m() { - return this.c - } - /** @private */ - get p() { return this.c } - /** @private */ - set p(value) { this.c = value } -} diff --git a/tests/cases/conformance/jsdoc/jsdocAccessibilityTagsDeclarations.ts b/tests/cases/conformance/jsdoc/jsdocAccessibilityTagsDeclarations.ts new file mode 100644 index 0000000000000..cfc488a972e4d --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAccessibilityTagsDeclarations.ts @@ -0,0 +1,37 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @out: foo.js +// @declaration: true +// @Filename: jsdocAccessibilityTagDeclarations.js +class Protected { + /** @protected */ + constructor(c) { + /** @protected */ + this.c = c + } + /** @protected */ + m() { + return this.c + } + /** @protected */ + get p() { return this.c } + /** @protected */ + set p(value) { this.c = value } +} + +class Private { + /** @private */ + constructor(c) { + /** @private */ + this.c = c + } + /** @private */ + m() { + return this.c + } + /** @private */ + get p() { return this.c } + /** @private */ + set p(value) { this.c = value } +}