Skip to content
Merged
48 changes: 36 additions & 12 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -5833,6 +5833,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
Expand All @@ -5844,34 +5846,35 @@ 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) {
const result: AccessorDeclaration[] = [];
if (p.flags & SymbolFlags.SetAccessor) {
result.push(setTextRange(createSetAccessor(
/*decorators*/ undefined,
createModifiersFromModifierFlags(staticFlag),
createModifiersFromModifierFlags(flag),
name,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*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));
}
Expand All @@ -5882,10 +5885,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
Expand All @@ -5894,13 +5897,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);
Expand Down Expand Up @@ -6088,6 +6102,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 = [];
Expand Down Expand Up @@ -28336,8 +28360,8 @@ namespace ts {
const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(node), otherKind);
if (otherAccessor) {
const nodeFlags = getModifierFlags(node);
const otherFlags = getModifierFlags(otherAccessor);
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);
}
Expand Down
18 changes: 15 additions & 3 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +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:
return visitNode(cbNode, (node as JSDocTag).tagName);
case SyntaxKind.PartiallyEmittedExpression:
return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
Expand Down Expand Up @@ -6826,7 +6829,16 @@ namespace ts {
break;
case "class":
case "constructor":
tag = parseClassTag(start, tagName);
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 "this":
tag = parseThisTag(start, tagName);
Expand Down Expand Up @@ -7192,8 +7204,8 @@ namespace ts {
return node;
}

function parseClassTag(start: number, tagName: Identifier): JSDocClassTag {
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, start);
function parseSimpleTag(start: number, kind: SyntaxKind, tagName: Identifier): JSDocTag {
const tag = <JSDocTag>createNode(kind, start);
tag.tagName = tagName;
return finishNode(tag);
}
Expand Down
17 changes: 7 additions & 10 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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: {
Expand All @@ -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:
Expand All @@ -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: {
Expand Down Expand Up @@ -1476,7 +1473,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;
Copy link
Member Author

@sandersn sandersn Dec 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the only substantive change in this file; all the others just eliminate checks that are already performed in ensureType.

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
Expand Down
15 changes: 15 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,9 @@ namespace ts {
JSDocAugmentsTag,
JSDocAuthorTag,
JSDocClassTag,
JSDocPublicTag,
JSDocPrivateTag,
JSDocProtectedTag,
JSDocCallbackTag,
JSDocEnumTag,
JSDocParameterTag,
Expand Down Expand Up @@ -2610,6 +2613,18 @@ namespace ts {
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;
Expand Down
15 changes: 14 additions & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -4128,6 +4128,19 @@ namespace ts {
return flags;
}

export function getEffectiveModifierFlags(node: Node) {
const flags = getModifierFlags(node);
if (!!node.parent && isInJSFile(node)) {
Copy link
Member

@weswigham weswigham Dec 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you just integrate this into getModifierFlagsNoCache? (Thus simultaneously caching the result and preventing the need for a separate getEffectiveModifierFlags function) It already has special logic for isInJSDocNamespace stuff, so...

// 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);
return flags | tags;
}
return flags;
}

export function modifierToFlag(token: SyntaxKind): ModifierFlags {
switch (token) {
case SyntaxKind.StaticKeyword: return ModifierFlags.Static;
Expand Down
31 changes: 29 additions & 2 deletions src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -673,6 +673,21 @@ 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);
}

/** Gets the JSDoc protected tag for the node if present */
export function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined {
return getFirstJSDocTag(node, isJSDocProtectedTag);
}

/** Gets the JSDoc enum tag for the node if present */
export function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined {
return getFirstJSDocTag(node, isJSDocEnumTag);
Expand Down Expand Up @@ -1547,6 +1562,18 @@ 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;
}

export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag {
return node.kind === SyntaxKind.JSDocProtectedTag;
}

export function isJSDocEnumTag(node: Node): node is JSDocEnumTag {
return node.kind === SyntaxKind.JSDocEnumTag;
}
Expand Down Expand Up @@ -2469,4 +2496,4 @@ namespace ts {
}

// #endregion
}
}
Loading