Skip to content

Commit 428d327

Browse files
committed
Fix incorrect flags in modifierFlagsCache
1 parent d9d027d commit 428d327

File tree

5 files changed

+86
-21
lines changed

5 files changed

+86
-21
lines changed

src/compiler/types.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -863,13 +863,14 @@ export const enum ModifierFlags {
863863
Async = 1 << 9, // Property/Method/Function
864864
Default = 1 << 10, // Function/Class (export default declaration)
865865
Const = 1 << 11, // Const enum
866-
HasComputedJSDocModifiers = 1 << 12, // Indicates the computed modifier flags include modifiers from JSDoc.
867-
868-
Deprecated = 1 << 13, // Deprecated tag.
869-
Override = 1 << 14, // Override method.
870-
In = 1 << 15, // Contravariance modifier
871-
Out = 1 << 16, // Covariance modifier
872-
Decorator = 1 << 17, // Contains a decorator.
866+
Deprecated = 1 << 12, // Deprecated tag.
867+
Override = 1 << 13, // Override method.
868+
In = 1 << 14, // Contravariance modifier
869+
Out = 1 << 15, // Covariance modifier
870+
Decorator = 1 << 16, // Contains a decorator.
871+
872+
HasComputedJSDocModifiers = 1 << 27, // Indicates the computed modifier flags include modifiers from JSDoc.
873+
HasExcessJDocModifiers = 1 << 28, // Indicates that there are JSDoc modifiers that are not in the cache and must be recalculated. For use with nodes in TS files only.
873874
HasComputedFlags = 1 << 29, // Modifier flags have been computed
874875

875876
AccessibilityModifier = Public | Private | Protected,
@@ -878,6 +879,7 @@ export const enum ModifierFlags {
878879
NonPublicAccessibilityModifier = Private | Protected,
879880

880881
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override | In | Out,
882+
JSDocOnlyModifier = Deprecated,
881883
ExportDefault = Export | Default,
882884
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Accessor | Async | Default | Const | Deprecated | Override | In | Out | Decorator,
883885
Modifier = All & ~Decorator,

src/compiler/utilities.ts

+33-3
Original file line numberDiff line numberDiff line change
@@ -6924,15 +6924,45 @@ function getModifierFlagsWorker(node: Node, includeJSDoc: boolean, alwaysInclude
69246924
return ModifierFlags.None;
69256925
}
69266926

6927+
// Calculate the modifier flags for a given node, and cache them based on the file containing the node.
6928+
// For a TypeScript file, the cache will only contain syntactic modifiers and potentially the `Deprecated` JSDoc modifier.
6929+
// For a JavaScript file, the cache will contain both syntactic and JSDoc modifiers.
6930+
69276931
if (!(node.modifierFlagsCache & ModifierFlags.HasComputedFlags)) {
69286932
node.modifierFlagsCache = getSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags;
69296933
}
69306934

6931-
if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && (alwaysIncludeJSDoc || isInJSFile(node)) && node.parent) {
6932-
node.modifierFlagsCache |= getJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers;
6935+
let jsdocModifierFlags: ModifierFlags | undefined;
6936+
if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && node.parent) {
6937+
jsdocModifierFlags = getJSDocModifierFlagsNoCache(node);
6938+
if (isInJSFile(node)) {
6939+
node.modifierFlagsCache |= jsdocModifierFlags | ModifierFlags.HasComputedJSDocModifiers;
6940+
}
6941+
else {
6942+
node.modifierFlagsCache |= (jsdocModifierFlags & ModifierFlags.Deprecated) | ModifierFlags.HasComputedJSDocModifiers;
6943+
if (jsdocModifierFlags & ~node.modifierFlagsCache & ~ModifierFlags.Deprecated) {
6944+
// If there are other JSDoc modifiers aside from `@deprecated` that aren't also in the set of syntactic modifiers for the node,
6945+
// we can add a flag indicating we need to recompute JSDoc modifiers when `alwaysIncludeJSDoc` is true.
6946+
node.modifierFlagsCache |= ModifierFlags.HasExcessJDocModifiers;
6947+
}
6948+
}
69336949
}
69346950

6935-
return node.modifierFlagsCache & ~(ModifierFlags.HasComputedFlags | ModifierFlags.HasComputedJSDocModifiers);
6951+
const modifiers = node.modifierFlagsCache & ~(ModifierFlags.HasComputedFlags | ModifierFlags.HasComputedJSDocModifiers | ModifierFlags.HasExcessJDocModifiers);
6952+
if (includeJSDoc || alwaysIncludeJSDoc) {
6953+
if (!isInJSFile(node) && alwaysIncludeJSDoc && node.modifierFlagsCache & ModifierFlags.HasExcessJDocModifiers) {
6954+
// If we are requesting JSDoc modifiers in a TS file, we only need to recalculate additional JSDoc modifiers if the cache indicates there are any to find.
6955+
// We recalculate the JSDoc modifiers since they may overlap with the syntactic modifiers in the cache. While this isn't as efficient as caching the modifiers,
6956+
// it is rare to use JSDoc for modifiers like `@private` in a TS file.
6957+
jsdocModifierFlags ??= getJSDocModifierFlagsNoCache(node);
6958+
return modifiers | jsdocModifierFlags;
6959+
}
6960+
return modifiers;
6961+
}
6962+
else {
6963+
// We are requesting only syntactic modifiers. filter out any JSDoc modifiers in the cache.
6964+
return (isInJSFile(node) ? modifiers & ~ModifierFlags.TypeScriptModifier : modifiers) & ~ModifierFlags.JSDocOnlyModifier;
6965+
}
69366966
}
69376967

69386968
/**

src/testRunner/unittests/publicApi.ts

+31
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,34 @@ describe("unittests:: Public APIs:: getChild* methods on EndOfFileToken with JSD
231231
assert.notEqual(endOfFileToken.getChildAt(0), /*expected*/ undefined);
232232
});
233233
});
234+
235+
describe("unittests:: Public APIs:: get syntactic and effective modifiers", () => {
236+
it("caches and reports correct flags in TS file", () => {
237+
// https://github.com/microsoft/TypeScript/issues/42189
238+
const content = `
239+
class C {
240+
/** @private */
241+
prop = 1;
242+
}`;
243+
const sourceFile = ts.createSourceFile("/file.ts", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true);
244+
const classNode = sourceFile.statements[0] as ts.ClassDeclaration;
245+
const propNode = classNode.members[0] as ts.PropertyDeclaration;
246+
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
247+
assert.equal(ts.ModifierFlags.None, ts.getEffectiveModifierFlags(propNode));
248+
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
249+
});
250+
it("caches and reports correct flags in JS file", () => {
251+
// https://github.com/microsoft/TypeScript/issues/42189
252+
const content = `
253+
class C {
254+
/** @private */
255+
prop = 1;
256+
}`;
257+
const sourceFile = ts.createSourceFile("/file.js", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true);
258+
const classNode = sourceFile.statements[0] as ts.ClassDeclaration;
259+
const propNode = classNode.members[0] as ts.PropertyDeclaration;
260+
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
261+
assert.equal(ts.ModifierFlags.Private, ts.getEffectiveModifierFlags(propNode));
262+
assert.equal(ts.ModifierFlags.None, ts.getSyntacticModifierFlags(propNode));
263+
});
264+
});

tests/baselines/reference/api/typescript.d.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -4764,20 +4764,22 @@ declare namespace ts {
47644764
Async = 512,
47654765
Default = 1024,
47664766
Const = 2048,
4767-
HasComputedJSDocModifiers = 4096,
4768-
Deprecated = 8192,
4769-
Override = 16384,
4770-
In = 32768,
4771-
Out = 65536,
4772-
Decorator = 131072,
4767+
Deprecated = 4096,
4768+
Override = 8192,
4769+
In = 16384,
4770+
Out = 32768,
4771+
Decorator = 65536,
4772+
HasComputedJSDocModifiers = 134217728,
4773+
HasExcessJDocModifiers = 268435456,
47734774
HasComputedFlags = 536870912,
47744775
AccessibilityModifier = 28,
4775-
ParameterPropertyModifier = 16476,
4776+
ParameterPropertyModifier = 8284,
47764777
NonPublicAccessibilityModifier = 24,
4777-
TypeScriptModifier = 117086,
4778+
TypeScriptModifier = 59742,
4779+
JSDocOnlyModifier = 4096,
47784780
ExportDefault = 1025,
4779-
All = 258047,
4780-
Modifier = 126975,
4781+
All = 131071,
4782+
Modifier = 65535,
47814783
}
47824784
enum JsxFlags {
47834785
None = 0,

tests/baselines/reference/jsFileCompilationPublicParameterModifier.symbols

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
=== a.js ===
44
class C { constructor(public x) { }}
55
>C : Symbol(C, Decl(a.js, 0, 0))
6-
>x : Symbol(C.x, Decl(a.js, 0, 22))
6+
>x : Symbol(x, Decl(a.js, 0, 22))
77

0 commit comments

Comments
 (0)