Skip to content

Commit

Permalink
Fix incorrect flags in modifierFlagsCache (#56198)
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton authored Oct 25, 2023
1 parent 55395f9 commit 79da510
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 56 deletions.
58 changes: 39 additions & 19 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,25 +851,45 @@ export const enum NodeFlags {
// dprint-ignore
export const enum ModifierFlags {
None = 0,
Export = 1 << 0, // Declarations
Ambient = 1 << 1, // Declarations
Public = 1 << 2, // Property/Method
Private = 1 << 3, // Property/Method
Protected = 1 << 4, // Property/Method
Static = 1 << 5, // Property/Method
Readonly = 1 << 6, // Property/Method
Accessor = 1 << 7, // Property
Abstract = 1 << 8, // Class/Method/ConstructSignature
Async = 1 << 9, // Property/Method/Function
Default = 1 << 10, // Function/Class (export default declaration)
Const = 1 << 11, // Const enum
HasComputedJSDocModifiers = 1 << 12, // Indicates the computed modifier flags include modifiers from JSDoc.

Deprecated = 1 << 13, // Deprecated tag.
Override = 1 << 14, // Override method.
In = 1 << 15, // Contravariance modifier
Out = 1 << 16, // Covariance modifier
Decorator = 1 << 17, // Contains a decorator.

// Syntactic/JSDoc modifiers
Public = 1 << 0, // Property/Method
Private = 1 << 1, // Property/Method
Protected = 1 << 2, // Property/Method
Readonly = 1 << 3, // Property/Method
Override = 1 << 4, // Override method.

// Syntactic-only modifiers
Export = 1 << 5, // Declarations
Abstract = 1 << 6, // Class/Method/ConstructSignature
Ambient = 1 << 7, // Declarations
Static = 1 << 8, // Property/Method
Accessor = 1 << 9, // Property
Async = 1 << 10, // Property/Method/Function
Default = 1 << 11, // Function/Class (export default declaration)
Const = 1 << 12, // Const enum
In = 1 << 13, // Contravariance modifier
Out = 1 << 14, // Covariance modifier
Decorator = 1 << 15, // Contains a decorator.

// JSDoc-only modifiers
Deprecated = 1 << 16, // Deprecated tag.

// Cache-only JSDoc-modifiers. Should match order of Syntactic/JSDoc modifiers, above.
/** @internal */ JSDocPublic = 1 << 23, // if this value changes, `selectEffectiveModifierFlags` must change accordingly
/** @internal */ JSDocPrivate = 1 << 24,
/** @internal */ JSDocProtected = 1 << 25,
/** @internal */ JSDocReadonly = 1 << 26,
/** @internal */ JSDocOverride = 1 << 27,

/** @internal */ SyntacticOrJSDocModifiers = Public | Private | Protected | Readonly | Override,
/** @internal */ SyntacticOnlyModifiers = Export | Ambient | Abstract | Static | Accessor | Async | Default | Const | In | Out | Decorator,
/** @internal */ SyntacticModifiers = SyntacticOrJSDocModifiers | SyntacticOnlyModifiers,
/** @internal */ JSDocCacheOnlyModifiers = JSDocPublic | JSDocPrivate | JSDocProtected | JSDocReadonly | JSDocOverride,
/** @internal */ JSDocOnlyModifiers = Deprecated,
/** @internal */ NonCacheOnlyModifiers = SyntacticOrJSDocModifiers | SyntacticOnlyModifiers | JSDocOnlyModifiers,

HasComputedJSDocModifiers = 1 << 28, // Indicates the computed modifier flags include modifiers from JSDoc.
HasComputedFlags = 1 << 29, // Modifier flags have been computed

AccessibilityModifier = Public | Private | Protected,
Expand Down
34 changes: 25 additions & 9 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6928,11 +6928,14 @@ function getModifierFlagsWorker(node: Node, includeJSDoc: boolean, alwaysInclude
node.modifierFlagsCache = getSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags;
}

if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && (alwaysIncludeJSDoc || isInJSFile(node)) && node.parent) {
node.modifierFlagsCache |= getJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers;
if (alwaysIncludeJSDoc || includeJSDoc && isInJSFile(node)) {
if (!(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && node.parent) {
node.modifierFlagsCache |= getRawJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers;
}
return selectEffectiveModifierFlags(node.modifierFlagsCache);
}

return node.modifierFlagsCache & ~(ModifierFlags.HasComputedFlags | ModifierFlags.HasComputedJSDocModifiers);
return selectSyntacticModifierFlags(node.modifierFlagsCache);
}

/**
Expand Down Expand Up @@ -6962,22 +6965,35 @@ export function getSyntacticModifierFlags(node: Node): ModifierFlags {
return getModifierFlagsWorker(node, /*includeJSDoc*/ false);
}

function getJSDocModifierFlagsNoCache(node: Node): ModifierFlags {
function getRawJSDocModifierFlagsNoCache(node: Node): ModifierFlags {
let flags = ModifierFlags.None;
if (!!node.parent && !isParameter(node)) {
if (isInJSFile(node)) {
if (getJSDocPublicTagNoCache(node)) flags |= ModifierFlags.Public;
if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.Private;
if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.Protected;
if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.Readonly;
if (getJSDocOverrideTagNoCache(node)) flags |= ModifierFlags.Override;
if (getJSDocPublicTagNoCache(node)) flags |= ModifierFlags.JSDocPublic;
if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.JSDocPrivate;
if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.JSDocProtected;
if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.JSDocReadonly;
if (getJSDocOverrideTagNoCache(node)) flags |= ModifierFlags.JSDocOverride;
}
if (getJSDocDeprecatedTagNoCache(node)) flags |= ModifierFlags.Deprecated;
}

return flags;
}

function selectSyntacticModifierFlags(flags: ModifierFlags) {
return flags & ModifierFlags.SyntacticModifiers;
}

function selectEffectiveModifierFlags(flags: ModifierFlags) {
return (flags & ModifierFlags.NonCacheOnlyModifiers) |
((flags & ModifierFlags.JSDocCacheOnlyModifiers) >>> 23); // shift ModifierFlags.JSDoc* to match ModifierFlags.*
}

function getJSDocModifierFlagsNoCache(node: Node): ModifierFlags {
return selectEffectiveModifierFlags(getRawJSDocModifierFlagsNoCache(node));
}

/**
* Gets the effective ModifierFlags for the provided node, including JSDoc modifiers. The modifier flags cache on the node is ignored.
*
Expand Down
5 changes: 2 additions & 3 deletions src/services/codefixes/fixSpelling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
getModeForUsageLocation,
getTextOfNode,
getTokenAtPosition,
hasSyntacticModifier,
hasOverrideModifier,
ImportDeclaration,
isBinaryExpression,
isClassElement,
Expand All @@ -27,7 +27,6 @@ import {
isPropertyAccessExpression,
isQualifiedName,
isStringLiteralLike,
ModifierFlags,
Node,
NodeFlags,
ScriptTarget,
Expand Down Expand Up @@ -131,7 +130,7 @@ function getInfo(sourceFile: SourceFile, pos: number, context: CodeFixContextBas
const props = checker.getContextualTypeForArgumentAtIndex(tag, 0);
suggestedSymbol = checker.getSuggestedSymbolForNonexistentJSXAttribute(node, props!);
}
else if (hasSyntacticModifier(parent, ModifierFlags.Override) && isClassElement(parent) && parent.name === node) {
else if (hasOverrideModifier(parent) && isClassElement(parent) && parent.name === node) {
const baseDeclaration = findAncestor(node, isClassLike);
const baseTypeNode = baseDeclaration ? getEffectiveBaseTypeNode(baseDeclaration) : undefined;
const baseType = baseTypeNode ? checker.getTypeAtLocation(baseTypeNode) : undefined;
Expand Down
31 changes: 31 additions & 0 deletions src/testRunner/unittests/publicApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,34 @@ describe("unittests:: Public APIs:: getChild* methods on EndOfFileToken with JSD
assert.notEqual(endOfFileToken.getChildAt(0), /*expected*/ undefined);
});
});

describe("unittests:: Public APIs:: get syntactic and effective modifiers", () => {
it("caches and reports correct flags in TS file", () => {
// https://github.com/microsoft/TypeScript/issues/42189
const content = `
class C {
/** @private */
prop = 1;
}`;
const sourceFile = ts.createSourceFile("/file.ts", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true);
const classNode = sourceFile.statements[0] as ts.ClassDeclaration;
const propNode = classNode.members[0] as ts.PropertyDeclaration;
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
assert.equal(ts.ModifierFlags.None, ts.getEffectiveModifierFlags(propNode));
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
});
it("caches and reports correct flags in JS file", () => {
// https://github.com/microsoft/TypeScript/issues/42189
const content = `
class C {
/** @private */
prop = 1;
}`;
const sourceFile = ts.createSourceFile("/file.js", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true);
const classNode = sourceFile.statements[0] as ts.ClassDeclaration;
const propNode = classNode.members[0] as ts.PropertyDeclaration;
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
assert.equal(ts.ModifierFlags.Private, ts.getEffectiveModifierFlags(propNode));
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
});
});
50 changes: 25 additions & 25 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4752,32 +4752,32 @@ declare namespace ts {
}
enum ModifierFlags {
None = 0,
Export = 1,
Ambient = 2,
Public = 4,
Private = 8,
Protected = 16,
Static = 32,
Readonly = 64,
Accessor = 128,
Abstract = 256,
Async = 512,
Default = 1024,
Const = 2048,
HasComputedJSDocModifiers = 4096,
Deprecated = 8192,
Override = 16384,
In = 32768,
Out = 65536,
Decorator = 131072,
Public = 1,
Private = 2,
Protected = 4,
Readonly = 8,
Override = 16,
Export = 32,
Abstract = 64,
Ambient = 128,
Static = 256,
Accessor = 512,
Async = 1024,
Default = 2048,
Const = 4096,
In = 8192,
Out = 16384,
Decorator = 32768,
Deprecated = 65536,
HasComputedJSDocModifiers = 268435456,
HasComputedFlags = 536870912,
AccessibilityModifier = 28,
ParameterPropertyModifier = 16476,
NonPublicAccessibilityModifier = 24,
TypeScriptModifier = 117086,
ExportDefault = 1025,
All = 258047,
Modifier = 126975,
AccessibilityModifier = 7,
ParameterPropertyModifier = 31,
NonPublicAccessibilityModifier = 6,
TypeScriptModifier = 28895,
ExportDefault = 2080,
All = 131071,
Modifier = 98303,
}
enum JsxFlags {
None = 0,
Expand Down

0 comments on commit 79da510

Please sign in to comment.