Add support for vscode-js-debug's customDescriptionGenerators (#40308)
This commit is contained in:
parent
38cedc5b5f
commit
d89635381a
14
.vscode/launch.template.json
vendored
14
.vscode/launch.template.json
vendored
|
@ -47,14 +47,24 @@
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"outFiles": [
|
"outFiles": [
|
||||||
"${workspaceRoot}/built/local/run.js"
|
"${workspaceRoot}/built/local/run.js"
|
||||||
]
|
],
|
||||||
|
|
||||||
|
// NOTE: To use this, you must switch the "type" above to "pwa-node". You may also need to follow the instructions
|
||||||
|
// here: https://github.com/microsoft/vscode-js-debug#nightly-extension to use the js-debug nightly until
|
||||||
|
// this feature is shipping in insiders or to a release:
|
||||||
|
// "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// See: https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code
|
// See: https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
"name": "Attach to VS Code TS Server via Port",
|
"name": "Attach to VS Code TS Server via Port",
|
||||||
"processId": "${command:PickProcess}"
|
"processId": "${command:PickProcess}",
|
||||||
|
|
||||||
|
// NOTE: To use this, you must switch the "type" above to "pwa-node". You may also need to follow the instructions
|
||||||
|
// here: https://github.com/microsoft/vscode-js-debug#nightly-extension to use the js-debug nightly until
|
||||||
|
// this feature is shipping in insiders or to a release:
|
||||||
|
// "customDescriptionGenerator": "'__tsDebuggerDisplay' in this ? this.__tsDebuggerDisplay(defaultValue) : defaultValue"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,6 +371,10 @@ namespace ts {
|
||||||
return formatEnum(flags, (<any>ts).ObjectFlags, /*isFlags*/ true);
|
return formatEnum(flags, (<any>ts).ObjectFlags, /*isFlags*/ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatFlowFlags(flags: FlowFlags | undefined): string {
|
||||||
|
return formatEnum(flags, (<any>ts).FlowFlags, /*isFlags*/ true);
|
||||||
|
}
|
||||||
|
|
||||||
let isDebugInfoEnabled = false;
|
let isDebugInfoEnabled = false;
|
||||||
|
|
||||||
interface ExtendedDebugModule {
|
interface ExtendedDebugModule {
|
||||||
|
@ -396,13 +400,87 @@ namespace ts {
|
||||||
return extendedDebug().formatControlFlowGraph(flowNode);
|
return extendedDebug().formatControlFlowGraph(flowNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function attachFlowNodeDebugInfo(flowNode: FlowNode) {
|
let flowNodeProto: FlowNodeBase | undefined;
|
||||||
|
|
||||||
|
function attachFlowNodeDebugInfoWorker(flowNode: FlowNodeBase) {
|
||||||
|
if (!("__debugFlowFlags" in flowNode)) { // eslint-disable-line no-in-operator
|
||||||
|
Object.defineProperties(flowNode, {
|
||||||
|
// for use with vscode-js-debug's new customDescriptionGenerator in launch.json
|
||||||
|
__tsDebuggerDisplay: {
|
||||||
|
value(this: FlowNodeBase) {
|
||||||
|
const flowHeader =
|
||||||
|
this.flags & FlowFlags.Start ? "FlowStart" :
|
||||||
|
this.flags & FlowFlags.BranchLabel ? "FlowBranchLabel" :
|
||||||
|
this.flags & FlowFlags.LoopLabel ? "FlowLoopLabel" :
|
||||||
|
this.flags & FlowFlags.Assignment ? "FlowAssignment" :
|
||||||
|
this.flags & FlowFlags.TrueCondition ? "FlowTrueCondition" :
|
||||||
|
this.flags & FlowFlags.FalseCondition ? "FlowFalseCondition" :
|
||||||
|
this.flags & FlowFlags.SwitchClause ? "FlowSwitchClause" :
|
||||||
|
this.flags & FlowFlags.ArrayMutation ? "FlowArrayMutation" :
|
||||||
|
this.flags & FlowFlags.Call ? "FlowCall" :
|
||||||
|
this.flags & FlowFlags.ReduceLabel ? "FlowReduceLabel" :
|
||||||
|
this.flags & FlowFlags.Unreachable ? "FlowUnreachable" :
|
||||||
|
"UnknownFlow";
|
||||||
|
const remainingFlags = this.flags & ~(FlowFlags.Referenced - 1);
|
||||||
|
return `${flowHeader}${remainingFlags ? ` (${formatFlowFlags(remainingFlags)})`: ""}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
__debugFlowFlags: { get(this: FlowNodeBase) { return formatEnum(this.flags, (ts as any).FlowFlags, /*isFlags*/ true); } },
|
||||||
|
__debugToString: { value(this: FlowNodeBase) { return formatControlFlowGraph(this); } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function attachFlowNodeDebugInfo(flowNode: FlowNodeBase) {
|
||||||
if (isDebugInfoEnabled) {
|
if (isDebugInfoEnabled) {
|
||||||
if (!("__debugFlowFlags" in flowNode)) { // eslint-disable-line no-in-operator
|
if (typeof Object.setPrototypeOf === "function") {
|
||||||
Object.defineProperties(flowNode, {
|
// if we're in es2015, attach the method to a shared prototype for `FlowNode`
|
||||||
__debugFlowFlags: { get(this: FlowNode) { return formatEnum(this.flags, (ts as any).FlowFlags, /*isFlags*/ true); } },
|
// so the method doesn't show up in the watch window.
|
||||||
__debugToString: { value(this: FlowNode) { return formatControlFlowGraph(this); } }
|
if (!flowNodeProto) {
|
||||||
});
|
flowNodeProto = Object.create(Object.prototype) as FlowNodeBase;
|
||||||
|
attachFlowNodeDebugInfoWorker(flowNodeProto);
|
||||||
|
}
|
||||||
|
Object.setPrototypeOf(flowNode, flowNodeProto);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// not running in an es2015 environment, attach the method directly.
|
||||||
|
attachFlowNodeDebugInfoWorker(flowNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let nodeArrayProto: NodeArray<Node> | undefined;
|
||||||
|
|
||||||
|
function attachNodeArrayDebugInfoWorker(array: NodeArray<Node>) {
|
||||||
|
if (!("__tsDebuggerDisplay" in array)) { // eslint-disable-line no-in-operator
|
||||||
|
Object.defineProperties(array, {
|
||||||
|
__tsDebuggerDisplay: {
|
||||||
|
value(this: NodeArray<Node>, defaultValue: string) {
|
||||||
|
// An `Array` with extra properties is rendered as `[A, B, prop1: 1, prop2: 2]`. Most of
|
||||||
|
// these aren't immediately useful so we trim off the `prop1: ..., prop2: ...` part from the
|
||||||
|
// formatted string.
|
||||||
|
defaultValue = String(defaultValue).replace(/(?:,[\s\w\d_]+:[^,]+)+\]$/, "]");
|
||||||
|
return `NodeArray ${defaultValue}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function attachNodeArrayDebugInfo(array: NodeArray<Node>) {
|
||||||
|
if (isDebugInfoEnabled) {
|
||||||
|
if (typeof Object.setPrototypeOf === "function") {
|
||||||
|
// if we're in es2015, attach the method to a shared prototype for `NodeArray`
|
||||||
|
// so the method doesn't show up in the watch window.
|
||||||
|
if (!nodeArrayProto) {
|
||||||
|
nodeArrayProto = Object.create(Array.prototype) as NodeArray<Node>;
|
||||||
|
attachNodeArrayDebugInfoWorker(nodeArrayProto);
|
||||||
|
}
|
||||||
|
Object.setPrototypeOf(array, nodeArrayProto);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// not running in an es2015 environment, attach the method directly.
|
||||||
|
attachNodeArrayDebugInfoWorker(array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,10 +512,51 @@ namespace ts {
|
||||||
|
|
||||||
// Add additional properties in debug mode to assist with debugging.
|
// Add additional properties in debug mode to assist with debugging.
|
||||||
Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, {
|
Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, {
|
||||||
|
// for use with vscode-js-debug's new customDescriptionGenerator in launch.json
|
||||||
|
__tsDebuggerDisplay: {
|
||||||
|
value(this: Symbol) {
|
||||||
|
const symbolHeader =
|
||||||
|
this.flags & SymbolFlags.Transient ? "TransientSymbol" :
|
||||||
|
"Symbol";
|
||||||
|
const remainingSymbolFlags = this.flags & ~SymbolFlags.Transient;
|
||||||
|
return `${symbolHeader} '${symbolName(this)}'${remainingSymbolFlags ? ` (${formatSymbolFlags(remainingSymbolFlags)})` : ""}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
__debugFlags: { get(this: Symbol) { return formatSymbolFlags(this.flags); } }
|
__debugFlags: { get(this: Symbol) { return formatSymbolFlags(this.flags); } }
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperties(objectAllocator.getTypeConstructor().prototype, {
|
Object.defineProperties(objectAllocator.getTypeConstructor().prototype, {
|
||||||
|
// for use with vscode-js-debug's new customDescriptionGenerator in launch.json
|
||||||
|
__tsDebuggerDisplay: {
|
||||||
|
value(this: Type) {
|
||||||
|
const typeHeader =
|
||||||
|
this.flags & TypeFlags.Nullable ? "NullableType" :
|
||||||
|
this.flags & TypeFlags.StringOrNumberLiteral ? `LiteralType ${JSON.stringify((this as LiteralType).value)}` :
|
||||||
|
this.flags & TypeFlags.BigIntLiteral ? `LiteralType ${(this as BigIntLiteralType).value.negative ? "-" : ""}${(this as BigIntLiteralType).value.base10Value}n` :
|
||||||
|
this.flags & TypeFlags.UniqueESSymbol ? "UniqueESSymbolType" :
|
||||||
|
this.flags & TypeFlags.Enum ? "EnumType" :
|
||||||
|
this.flags & TypeFlags.Intrinsic ? `IntrinsicType ${(this as IntrinsicType).intrinsicName}` :
|
||||||
|
this.flags & TypeFlags.Union ? "UnionType" :
|
||||||
|
this.flags & TypeFlags.Intersection ? "IntersectionType" :
|
||||||
|
this.flags & TypeFlags.Index ? "IndexType" :
|
||||||
|
this.flags & TypeFlags.IndexedAccess ? "IndexedAccessType" :
|
||||||
|
this.flags & TypeFlags.Conditional ? "ConditionalType" :
|
||||||
|
this.flags & TypeFlags.Substitution ? "SubstitutionType" :
|
||||||
|
this.flags & TypeFlags.TypeParameter ? "TypeParameter" :
|
||||||
|
this.flags & TypeFlags.Object ?
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.ClassOrInterface ? "InterfaceType" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.Reference ? "TypeReference" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.Tuple ? "TupleType" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.Anonymous ? "AnonymousType" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.Mapped ? "MappedType" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.ReverseMapped ? "ReverseMappedType" :
|
||||||
|
(this as ObjectType).objectFlags & ObjectFlags.EvolvingArray ? "EvolvingArrayType" :
|
||||||
|
"ObjectType" :
|
||||||
|
"Type";
|
||||||
|
const remainingObjectFlags = this.flags & TypeFlags.Object ? (this as ObjectType).objectFlags & ~ObjectFlags.ObjectTypeKindMask : 0;
|
||||||
|
return `${typeHeader}${this.symbol ? ` '${symbolName(this.symbol)}'` : ""}${remainingObjectFlags ? ` (${formatObjectFlags(remainingObjectFlags)})` : ""}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
__debugFlags: { get(this: Type) { return formatTypeFlags(this.flags); } },
|
__debugFlags: { get(this: Type) { return formatTypeFlags(this.flags); } },
|
||||||
__debugObjectFlags: { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((<ObjectType>this).objectFlags) : ""; } },
|
__debugObjectFlags: { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((<ObjectType>this).objectFlags) : ""; } },
|
||||||
__debugTypeToString: {
|
__debugTypeToString: {
|
||||||
|
@ -464,6 +583,50 @@ namespace ts {
|
||||||
for (const ctor of nodeConstructors) {
|
for (const ctor of nodeConstructors) {
|
||||||
if (!ctor.prototype.hasOwnProperty("__debugKind")) {
|
if (!ctor.prototype.hasOwnProperty("__debugKind")) {
|
||||||
Object.defineProperties(ctor.prototype, {
|
Object.defineProperties(ctor.prototype, {
|
||||||
|
// for use with vscode-js-debug's new customDescriptionGenerator in launch.json
|
||||||
|
__tsDebuggerDisplay: {
|
||||||
|
value(this: Node) {
|
||||||
|
const nodeHeader =
|
||||||
|
isGeneratedIdentifier(this) ? "GeneratedIdentifier" :
|
||||||
|
isIdentifier(this) ? `Identifier '${idText(this)}'` :
|
||||||
|
isPrivateIdentifier(this) ? `PrivateIdentifier '${idText(this)}'` :
|
||||||
|
isStringLiteral(this) ? `StringLiteral ${JSON.stringify(this.text.length < 10 ? this.text : this.text.slice(10) + "...")}` :
|
||||||
|
isNumericLiteral(this) ? `NumericLiteral ${this.text}` :
|
||||||
|
isBigIntLiteral(this) ? `BigIntLiteral ${this.text}n` :
|
||||||
|
isTypeParameterDeclaration(this) ? "TypeParameterDeclaration" :
|
||||||
|
isParameter(this) ? "ParameterDeclaration" :
|
||||||
|
isConstructorDeclaration(this) ? "ConstructorDeclaration" :
|
||||||
|
isGetAccessorDeclaration(this) ? "GetAccessorDeclaration" :
|
||||||
|
isSetAccessorDeclaration(this) ? "SetAccessorDeclaration" :
|
||||||
|
isCallSignatureDeclaration(this) ? "CallSignatureDeclaration" :
|
||||||
|
isConstructSignatureDeclaration(this) ? "ConstructSignatureDeclaration" :
|
||||||
|
isIndexSignatureDeclaration(this) ? "IndexSignatureDeclaration" :
|
||||||
|
isTypePredicateNode(this) ? "TypePredicateNode" :
|
||||||
|
isTypeReferenceNode(this) ? "TypeReferenceNode" :
|
||||||
|
isFunctionTypeNode(this) ? "FunctionTypeNode" :
|
||||||
|
isConstructorTypeNode(this) ? "ConstructorTypeNode" :
|
||||||
|
isTypeQueryNode(this) ? "TypeQueryNode" :
|
||||||
|
isTypeLiteralNode(this) ? "TypeLiteralNode" :
|
||||||
|
isArrayTypeNode(this) ? "ArrayTypeNode" :
|
||||||
|
isTupleTypeNode(this) ? "TupleTypeNode" :
|
||||||
|
isOptionalTypeNode(this) ? "OptionalTypeNode" :
|
||||||
|
isRestTypeNode(this) ? "RestTypeNode" :
|
||||||
|
isUnionTypeNode(this) ? "UnionTypeNode" :
|
||||||
|
isIntersectionTypeNode(this) ? "IntersectionTypeNode" :
|
||||||
|
isConditionalTypeNode(this) ? "ConditionalTypeNode" :
|
||||||
|
isInferTypeNode(this) ? "InferTypeNode" :
|
||||||
|
isParenthesizedTypeNode(this) ? "ParenthesizedTypeNode" :
|
||||||
|
isThisTypeNode(this) ? "ThisTypeNode" :
|
||||||
|
isTypeOperatorNode(this) ? "TypeOperatorNode" :
|
||||||
|
isIndexedAccessTypeNode(this) ? "IndexedAccessTypeNode" :
|
||||||
|
isMappedTypeNode(this) ? "MappedTypeNode" :
|
||||||
|
isLiteralTypeNode(this) ? "LiteralTypeNode" :
|
||||||
|
isNamedTupleMember(this) ? "NamedTupleMember" :
|
||||||
|
isImportTypeNode(this) ? "ImportTypeNode" :
|
||||||
|
formatSyntaxKind(this.kind);
|
||||||
|
return `${nodeHeader}${this.flags ? ` (${formatNodeFlags(this.flags)})` : ""}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
__debugKind: { get(this: Node) { return formatSyntaxKind(this.kind); } },
|
__debugKind: { get(this: Node) { return formatSyntaxKind(this.kind); } },
|
||||||
__debugNodeFlags: { get(this: Node) { return formatNodeFlags(this.flags); } },
|
__debugNodeFlags: { get(this: Node) { return formatNodeFlags(this.flags); } },
|
||||||
__debugModifierFlags: { get(this: Node) { return formatModifierFlags(getEffectiveModifierFlagsNoCache(this)); } },
|
__debugModifierFlags: { get(this: Node) { return formatModifierFlags(getEffectiveModifierFlagsNoCache(this)); } },
|
||||||
|
|
|
@ -509,6 +509,7 @@ namespace ts {
|
||||||
if (elements.transformFlags === undefined) {
|
if (elements.transformFlags === undefined) {
|
||||||
aggregateChildrenFlags(elements as MutableNodeArray<T>);
|
aggregateChildrenFlags(elements as MutableNodeArray<T>);
|
||||||
}
|
}
|
||||||
|
Debug.attachNodeArrayDebugInfo(elements);
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,6 +521,7 @@ namespace ts {
|
||||||
setTextRangePosEnd(array, -1, -1);
|
setTextRangePosEnd(array, -1, -1);
|
||||||
array.hasTrailingComma = !!hasTrailingComma;
|
array.hasTrailingComma = !!hasTrailingComma;
|
||||||
aggregateChildrenFlags(array);
|
aggregateChildrenFlags(array);
|
||||||
|
Debug.attachNodeArrayDebugInfo(array);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5021,7 +5021,11 @@ namespace ts {
|
||||||
/* @internal */
|
/* @internal */
|
||||||
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
|
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
|
||||||
/* @internal */
|
/* @internal */
|
||||||
PropagatingFlags = ContainsWideningType | ContainsObjectOrArrayLiteral | NonInferrableType
|
PropagatingFlags = ContainsWideningType | ContainsObjectOrArrayLiteral | NonInferrableType,
|
||||||
|
|
||||||
|
// Object flags that uniquely identify the kind of ObjectType
|
||||||
|
/* @internal */
|
||||||
|
ObjectTypeKindMask = ClassOrInterface | Reference | Tuple | Anonymous | Mapped | ReverseMapped | EvolvingArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
|
|
Loading…
Reference in a new issue