(response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments)
| 2851 | } |
| 2852 | |
| 2853 | protected async variablesRequest(response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments): Promise<void> { |
| 2854 | response.body = { variables: [] }; |
| 2855 | if (!this.isMIStatusStopped() || !this.stopped || this.disableSendStoppedEvents || this.continuing) { |
| 2856 | this.sendResponse(response); |
| 2857 | return; |
| 2858 | } |
| 2859 | let id: number | string | VariableObject | ExtendedVariable; |
| 2860 | |
| 2861 | /* |
| 2862 | // How to deal with multiple anonymous unions/structs in the same scope. gdb uses the same display name for |
| 2863 | // all of them. VSCode requires that all children have unique display names. So, we make them unique. The next |
| 2864 | // issue is should we use the programming model which essentially flattens the union/struct or the natural one. |
| 2865 | // We have three objectives we have to satisfy |
| 2866 | // |
| 2867 | // 1. Does it display correctly? |
| 2868 | // 2. Can I do 'Add to Watch' or 'Copy as Expression' in the Variables Window? |
| 2869 | // 3. Can I set a value on a field? |
| 2870 | // |
| 2871 | // We meet all three objectives, whether we flatten or not. I believe the natural model is better |
| 2872 | // because it is closely aligned with the source code. Visual Studio and Eclipse use the flattened model. |
| 2873 | // So, we have a config option to let the user decide. Not many people uae multiple anonymous stuff but |
| 2874 | // Zephyr OS does and since it is legal C, we have to try our best to support it. |
| 2875 | // |
| 2876 | // Note: VSCode has a bug where if a union member is modified by the user, it does not refresh the Variables window |
| 2877 | // but it will re-evaluate everything in the Watch window. Basically, it has no concept of a union and there is no |
| 2878 | // way I know of to force a refresh |
| 2879 | */ |
| 2880 | if (args.variablesReference === HandleRegions.GLOBAL_HANDLE_ID) { |
| 2881 | return this.globalVariablesRequest(response, args); |
| 2882 | } else if (args.variablesReference >= HandleRegions.STATIC_HANDLES_START && args.variablesReference <= HandleRegions.STATIC_HANDLES_FINISH) { |
| 2883 | const [threadId, frameId] = decodeReference(args.variablesReference); |
| 2884 | return this.staticVariablesRequest(threadId, frameId, response, args); |
| 2885 | } else if (args.variablesReference >= HandleRegions.STACK_HANDLES_START && args.variablesReference <= HandleRegions.STACK_HANDLES_FINISH) { |
| 2886 | return this.stackVariablesRequest(response, args); |
| 2887 | } else if (args.variablesReference >= HandleRegions.REG_HANDLE_START && args.variablesReference <= HandleRegions.REG_HANDLE_FINISH) { |
| 2888 | return this.registersRequest(response, args); |
| 2889 | } else { |
| 2890 | id = this.variableHandles.get(args.variablesReference); |
| 2891 | |
| 2892 | if (typeof id === 'string') { |
| 2893 | return this.variableMembersRequest(id, response, args); |
| 2894 | } |
| 2895 | else if (typeof id === 'object') { |
| 2896 | if (id instanceof VariableObject) { |
| 2897 | const pVar = id as VariableObject; |
| 2898 | |
| 2899 | // Variable members |
| 2900 | let children: VariableObject[]; |
| 2901 | const childMap: { [name: string]: number } = {}; |
| 2902 | try { |
| 2903 | children = await this.miDebugger.varListChildren(args.variablesReference, id.name); |
| 2904 | const vars = children.map((child) => { |
| 2905 | const varId = this.findOrCreateVariable(child); |
| 2906 | child.id = varId; |
| 2907 | if (/^\d+$/.test(child.exp)) { |
| 2908 | child.fullExp = `${pVar.fullExp || pVar.exp}[${child.exp}]`; |
| 2909 | } |
| 2910 | else { |
no test coverage detected