From 15ba98ad1b2f84c9bf9ac5697f9637c9b0b9b6a1 Mon Sep 17 00:00:00 2001 From: JackN Date: Mon, 17 Jan 2022 15:30:06 -0500 Subject: [PATCH 1/6] Fix to bring RUST logs from `probe-rs-debugger` to the console --- src/extension.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 795cf12..1cc48f3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -47,10 +47,14 @@ function handleExit(code: number | null, signal: string | null) { } } -// Messages to be sent to the debug session's console. Anything sent before or after an active debug session is silently ignored by VSCode. Ditto for any messages that doesn't start with 'ERROR', or 'INFO' , or 'WARN', ... unless the log level is DEBUG. Then everything is logged. -function logToConsole(consoleMesssage: string) { +// Messages to be sent to the debug session's console. +// Anything sent before or after an active debug session is silently ignored by VSCode. +// Any local (generated directly by this extension) messages MUST start with 'ERROR', or 'INFO' , 'WARN', `DEBUG`, or `TRACE` to match the RUST log behaviour. +// Any local messages that start with `CONSOLE` will ALWAYS be logged. +// Any messages that come from the `probe-rs-debugger` STDERR will always be logged, and will already conform with the RUST LOG setting. +function logToConsole(consoleMesssage: string, fromDebugger: boolean = false) { console.log(consoleMesssage); // During VSCode extension development, this will also log to the local debug console - if (consoleMesssage.includes('CONSOLE')) { + if (fromDebugger || consoleMesssage.includes('CONSOLE')) { vscode.debug.activeDebugConsole.appendLine(consoleMesssage); } else { switch (probeRsLogLevel) { @@ -267,9 +271,9 @@ class ProbeRSDebugAdapterServerDescriptorFactory implements vscode.DebugAdapterD }); launchedDebugAdapter.stderr?.on('data', (data: string) => { if (debuggerStatus === (DebuggerStatus.running as DebuggerStatus)) { - logToConsole("ERROR: " + data); + logToConsole(data, true); } else { - vscode.window.showErrorMessage("`probe-rs-debugger` error: " + data); + vscode.window.showErrorMessage("`probe-rs-debugger`: " + data); } }); launchedDebugAdapter.on('close', (code: number | null, signal: string | null) => { From c02b58ad9e4d66bda3bf84b63751ab46a538c481 Mon Sep 17 00:00:00 2001 From: JackN Date: Tue, 18 Jan 2022 14:48:35 -0500 Subject: [PATCH 2/6] bump dependencies and streamline logging --- package.json | 28 ++++++++--------- src/debugProtocol.json | 68 ++++++++++++++++++++++++++++++++---------- src/extension.ts | 22 +++++++------- 3 files changed, 76 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 78113dc..a9afd68 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "probe-rs-debugger", "displayName": "Debugger for probe-rs", - "version": "0.3.3", + "version": "0.3.4", "publisher": "probe-rs", "description": "probe-rs Debug Adapter for VS Code.", "author": { @@ -13,7 +13,7 @@ "probe-rs embedded debug" ], "engines": { - "vscode": "^1.62.2" + "vscode": "^1.63.2" }, "icon": "images/probe-rs-debugger.png", "categories": [ @@ -43,28 +43,28 @@ "watch-web": "webpack --watch --devtool nosources-source-map --config ./build/web-extension.webpack.config.js", "package-web": "webpack --mode production --config ./build/web-extension.webpack.config.js" }, - "enableProposedApi": false, + "enabledApiProposals": [], "dependencies": { "await-notify": "1.0.1", "portfinder": "^1.0.28", - "vscode-debugadapter": "^1.49.0" + "vscode-debugadapter": "^1.51.0" }, "devDependencies": { "@types/glob": "^7.2.0", "@types/mocha": "^9.0.0", - "@types/node": "^16.11.3", - "@types/vscode": "^1.61.0", - "@typescript-eslint/eslint-plugin": "^5.4.0", - "@typescript-eslint/parser": "^5.4.0", - "eslint": "^8.0.1", + "@types/node": "^17.0.9", + "@types/vscode": "^1.63.1", + "@typescript-eslint/eslint-plugin": "^5.10.0", + "@typescript-eslint/parser": "^5.10.0", + "eslint": "^8.7.0", "glob": "^7.2.0", - "mocha": "^9.1.3", + "mocha": "^9.1.4", "portfinder": "^1.0.28", "ts-loader": "^9.2.6", - "typescript": "^4.4.4", - "vsce": "^2.3.0", - "vscode-debugadapter-testsupport": "^1.49.0", - "webpack": "^5.64.1", + "typescript": "^4.5.4", + "vsce": "^2.6.3", + "vscode-debugadapter-testsupport": "^1.51.0", + "webpack": "^5.66.0", "webpack-cli": "^4.9.1" }, "main": "./dist/ext/extension.js", diff --git a/src/debugProtocol.json b/src/debugProtocol.json index d2ea49f..8bbe944 100644 --- a/src/debugProtocol.json +++ b/src/debugProtocol.json @@ -348,8 +348,15 @@ "properties": { "category": { "type": "string", - "description": "The output category. If not specified, 'console' is assumed.", - "_enum": [ "console", "stdout", "stderr", "telemetry" ] + "description": "The output category. If not specified or if the category is not understand by the client, 'console' is assumed.", + "_enum": [ "console", "important", "stdout", "stderr", "telemetry" ], + "enumDescriptions": [ + "Show the output in the client's default message UI, e.g. a 'debug console'. This category should only be used for informational output from the debugger (as opposed to the debuggee).", + "A hint for the client to show the ouput in the client's UI for important and highly visible information, e.g. as a popup notification. This category should only be used for important messages from the debugger (as opposed to the debuggee). Since this category value is a hint, clients might ignore the hint and assume the 'console' category.", + "Show the output as normal program output from the debuggee.", + "Show the output as error program output from the debuggee.", + "Send the output to telemetry instead of showing it to the user." + ] }, "output": { "type": "string", @@ -1378,7 +1385,7 @@ }, "name": { "type": "string", - "description": "The name of the Variable's child to obtain data breakpoint information for.\nIf variablesReference isn’t provided, this can be an expression." + "description": "The name of the Variable's child to obtain data breakpoint information for.\nIf variablesReference isn't provided, this can be an expression." } }, "required": [ "name" ] @@ -1531,7 +1538,7 @@ "ContinueRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to run again.", + "description": "The request resumes execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false.", "properties": { "command": { "type": "string", @@ -1550,7 +1557,11 @@ "properties": { "threadId": { "type": "integer", - "description": "Continue execution for the specified thread (if possible).\nIf the backend cannot continue on a single thread but will continue on all threads, it should set the 'allThreadsContinued' attribute in the response to true." + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, execution is resumed only for the thread with given 'threadId'." } }, "required": [ "threadId" ] @@ -1565,7 +1576,7 @@ "properties": { "allThreadsContinued": { "type": "boolean", - "description": "If true, the 'continue' request has ignored the specified thread and continued all threads instead.\nIf this attribute is missing a value of 'true' is assumed for backward compatibility." + "description": "The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed." } } } @@ -1577,7 +1588,7 @@ "NextRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to run again for one step.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", + "description": "The request executes one step (in the given granularity) for the specified thread and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", "properties": { "command": { "type": "string", @@ -1596,7 +1607,11 @@ "properties": { "threadId": { "type": "integer", - "description": "Execute 'next' for this thread." + "description": "Specifies the thread for which to resume execution for one step (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." }, "granularity": { "$ref": "#/definitions/SteppingGranularity", @@ -1615,7 +1630,7 @@ "StepInRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to step into a function/method if possible.\nIf it cannot step into a target, 'stepIn' behaves like 'next'.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nIf there are multiple function/method calls (or other targets) on the source line,\nthe optional argument 'targetId' can be used to control into which target the 'stepIn' should occur.\nThe list of possible targets for a given source line can be retrieved via the 'stepInTargets' request.", + "description": "The request resumes the given thread to step into a function/method and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nIf the request cannot step into a target, 'stepIn' behaves like the 'next' request.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nIf there are multiple function/method calls (or other targets) on the source line,\nthe optional argument 'targetId' can be used to control into which target the 'stepIn' should occur.\nThe list of possible targets for a given source line can be retrieved via the 'stepInTargets' request.", "properties": { "command": { "type": "string", @@ -1634,7 +1649,11 @@ "properties": { "threadId": { "type": "integer", - "description": "Execute 'stepIn' for this thread." + "description": "Specifies the thread for which to resume execution for one step-into (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." }, "targetId": { "type": "integer", @@ -1657,7 +1676,7 @@ "StepOutRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to run again for one step.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", + "description": "The request resumes the given thread to step out (return) from a function/method and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", "properties": { "command": { "type": "string", @@ -1676,7 +1695,11 @@ "properties": { "threadId": { "type": "integer", - "description": "Execute 'stepOut' for this thread." + "description": "Specifies the thread for which to resume execution for one step-out (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." }, "granularity": { "$ref": "#/definitions/SteppingGranularity", @@ -1695,7 +1718,7 @@ "StepBackRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to run one step backwards.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nClients should only call this request if the capability 'supportsStepBack' is true.", + "description": "The request executes one backward step (in the given granularity) for the specified thread and allows all other threads to run backward freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nClients should only call this request if the capability 'supportsStepBack' is true.", "properties": { "command": { "type": "string", @@ -1714,7 +1737,11 @@ "properties": { "threadId": { "type": "integer", - "description": "Execute 'stepBack' for this thread." + "description": "Specifies the thread for which to resume execution for one step backwards (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." }, "granularity": { "$ref": "#/definitions/SteppingGranularity", @@ -1733,7 +1760,7 @@ "ReverseContinueRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", - "description": "The request starts the debuggee to run backward.\nClients should only call this request if the capability 'supportsStepBack' is true.", + "description": "The request resumes backward execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false.\nClients should only call this request if the capability 'supportsStepBack' is true.", "properties": { "command": { "type": "string", @@ -1752,8 +1779,13 @@ "properties": { "threadId": { "type": "integer", - "description": "Execute 'reverseContinue' for this thread." + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, backward execution is resumed only for the thread with given 'threadId'." } + }, "required": [ "threadId" ] }, @@ -3109,6 +3141,10 @@ "supportsExceptionFilterOptions": { "type": "boolean", "description": "The debug adapter supports 'filterOptions' as an argument on the 'setExceptionBreakpoints' request." + }, + "supportsSingleThreadExecutionRequests": { + "type": "boolean", + "description": "The debug adapter supports the 'singleThread' property on the execution requests ('continue', 'next', 'stepIn', 'stepOut', 'reverseContinue', 'stepBack')." } } }, diff --git a/src/extension.ts b/src/extension.ts index 1cc48f3..1abc2fd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,7 +10,7 @@ import * as vscode from 'vscode'; import { DebugAdapterTracker, DebugAdapterTrackerFactory, } from 'vscode'; // This is just the default. It will be updated after the configuration has been resolved. -var probeRsLogLevel = 'Info'; +var probeRsLogLevel = 'Error'; export async function activate(context: vscode.ExtensionContext) { @@ -23,10 +23,10 @@ export async function activate(context: vscode.ExtensionContext) { ); // I cannot find a way to programmatically test for when VSCode is debugging the extension, versus when a user is using the extension to debug their own code, but the following code is usefull in the former situation, so I will leave it here to be commented out by extension developers when needed. - // const trackerFactory = new ProbeRsDebugAdapterTrackerFactory(); - // context.subscriptions.push( - // vscode.debug.registerDebugAdapterTrackerFactory('probe-rs-debug', trackerFactory), - // ); + const trackerFactory = new ProbeRsDebugAdapterTrackerFactory(); + context.subscriptions.push( + vscode.debug.registerDebugAdapterTrackerFactory('probe-rs-debug', trackerFactory), + ); } @@ -182,7 +182,10 @@ class ProbeRSDebugAdapterServerDescriptorFactory implements vscode.DebugAdapterD // - The decision was made during investigation of an [issue](https://github.com/probe-rs/probe-rs/issues/703) ... basically, after the probe-rs API was fixed, the code would work well for TCP connections (`DebugAdapterServer`), but would not work for STDIO connections (`DebugAdapterServer`). After some searches I found other extension developers that also found the TCP based connections to be more stable. // - Since then, we have taken advantage of the access to stderr that `DebugAdapterServer` offers to route `RUST_LOG` output from the debugger to the user's VSCode Debug Console. This is a very useful capability, and cannot easily be implemented in `DebugAdapterExecutable`, because it does not allow access to `stderr` [See ongoing issue in VScode repo](https://github.com/microsoft/vscode/issues/108145). async createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): Promise { - probeRsLogLevel = session.configuration.consoleLogLevel; + if (session.configuration.hasOwnProperty('consoleLogLevel')) { + probeRsLogLevel = session.configuration.consoleLogLevel.toLowerCase(); + }; + // Initiate either the 'attach' or 'launch' request. logToConsole("INFO: Session: " + JSON.stringify(session, null, 2)); @@ -223,15 +226,10 @@ class ProbeRSDebugAdapterServerDescriptorFactory implements vscode.DebugAdapterD args.push("--port"); args.push(debugServer[1]); - var logEnv = 'error'; //This is the default - if (session.configuration.hasOwnProperty('consoleLogLevel')) { - logEnv = session.configuration.consoleLogLevel.toLowerCase(); - }; - var options = { cwd: session.configuration.cwd, // eslint-disable-next-line @typescript-eslint/naming-convention - env: { ...process.env, 'RUST_LOG': logEnv, }, + env: { ...process.env, 'RUST_LOG': probeRsLogLevel, 'DEFMT_LOG': probeRsLogLevel }, windowsHide: true, }; From ebdb70816a29c85c16dbc535cfe7526dacd321cd Mon Sep 17 00:00:00 2001 From: JackN Date: Tue, 18 Jan 2022 14:49:10 -0500 Subject: [PATCH 3/6] disable DebugAdapterTrackerFactory --- src/extension.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 1abc2fd..89278f6 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,10 +23,10 @@ export async function activate(context: vscode.ExtensionContext) { ); // I cannot find a way to programmatically test for when VSCode is debugging the extension, versus when a user is using the extension to debug their own code, but the following code is usefull in the former situation, so I will leave it here to be commented out by extension developers when needed. - const trackerFactory = new ProbeRsDebugAdapterTrackerFactory(); - context.subscriptions.push( - vscode.debug.registerDebugAdapterTrackerFactory('probe-rs-debug', trackerFactory), - ); + // const trackerFactory = new ProbeRsDebugAdapterTrackerFactory(); + // context.subscriptions.push( + // vscode.debug.registerDebugAdapterTrackerFactory('probe-rs-debug', trackerFactory), + // ); } From eb7c87d05b006a76590a38432b3c5825cfa141c0 Mon Sep 17 00:00:00 2001 From: JackN Date: Wed, 19 Jan 2022 15:42:49 -0500 Subject: [PATCH 4/6] Catch log::error!() messages and display in client --- src/extension.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index 89278f6..488c800 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -54,7 +54,15 @@ function handleExit(code: number | null, signal: string | null) { // Any messages that come from the `probe-rs-debugger` STDERR will always be logged, and will already conform with the RUST LOG setting. function logToConsole(consoleMesssage: string, fromDebugger: boolean = false) { console.log(consoleMesssage); // During VSCode extension development, this will also log to the local debug console - if (fromDebugger || consoleMesssage.includes('CONSOLE')) { + if (fromDebugger) { + // Any messages that come directly from the debugger, are assumed to be RUST_LOG messages and should be logged to the console. + vscode.debug.activeDebugConsole.appendLine(consoleMesssage); + // The one exception is RUST_LOG messages of the `error` variant. These deserve to be shown as an error message in the UI also. + // This filter might capture more than expected, but since RUST_LOG messages can take many formats, it seems that this is the safest/most inclusive. + if (consoleMesssage.includes("ERROR")) { + vscode.window.showErrorMessage("`probe-rs-debugger`: " + consoleMesssage); + } + } else if (consoleMesssage.includes('CONSOLE')) { vscode.debug.activeDebugConsole.appendLine(consoleMesssage); } else { switch (probeRsLogLevel) { From 03c60e805013b935088ec7527143dc3937dc4539 Mon Sep 17 00:00:00 2001 From: JackN Date: Thu, 3 Feb 2022 12:47:31 -0500 Subject: [PATCH 5/6] Update dependencies and debugProtocol.json --- package.json | 8 +++----- src/debugProtocol.json | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index f191882..5baad24 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,10 @@ "package-web": "webpack --mode production --config ./build/web-extension.webpack.config.js" }, "enabledApiProposals": [], - "dependencies": { "@vscode/debugadapter": "^1.51.0", "await-notify": "1.0.1", - "portfinder": "^1.0.28", + "portfinder": "^1.0.28" }, "devDependencies": { "@types/glob": "^7.2.0", @@ -57,6 +56,7 @@ "@types/vscode": "^1.63.1", "@typescript-eslint/eslint-plugin": "^5.10.0", "@typescript-eslint/parser": "^5.10.1", + "@vscode/debugprotocol": "^1.51.0", "eslint": "^8.8.0", "glob": "^7.2.0", "mocha": "^9.2.0", @@ -64,10 +64,8 @@ "ts-loader": "^9.2.6", "typescript": "^4.5.5", "vsce": "^2.6.5", - "vscode-debugadapter-testsupport": "^1.51.0", "webpack": "^5.67.0", "webpack-cli": "^4.9.2" - }, "main": "./dist/ext/extension.js", "browser": "./dist/web/extension.js", @@ -374,4 +372,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/debugProtocol.json b/src/debugProtocol.json index 8bbe944..a000610 100644 --- a/src/debugProtocol.json +++ b/src/debugProtocol.json @@ -3495,7 +3495,7 @@ }, "value": { "type": "string", - "description": "The variable's value. This can be a multi-line text, e.g. for a function the body of a function." + "description": "The variable's value.\nThis can be a multi-line text, e.g. for a function the body of a function.\nFor structured variables (which do not have a simple value), it is recommended to provide a one line representation of the structured object. This helps to identify the structured object in the collapsed state when its children are not yet visible.\nAn empty string can be used if no value should be shown in the UI." }, "type": { "type": "string", From 60de50ac02384254863f28499f4f315433b80b60 Mon Sep 17 00:00:00 2001 From: JackN Date: Thu, 3 Feb 2022 15:32:46 -0500 Subject: [PATCH 6/6] Update VSCode 1.64.0 and dependencies --- package.json | 8 ++++---- src/debugProtocol.json | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5baad24..332aa61 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "probe-rs embedded debug" ], "engines": { - "vscode": "^1.63.2" + "vscode": "^1.64.0" }, "icon": "images/probe-rs-debugger.png", "categories": [ @@ -53,10 +53,10 @@ "@types/glob": "^7.2.0", "@types/mocha": "^9.1.0", "@types/node": "^17.0.13", - "@types/vscode": "^1.63.1", + "@types/vscode": "^1.64.0", "@typescript-eslint/eslint-plugin": "^5.10.0", "@typescript-eslint/parser": "^5.10.1", - "@vscode/debugprotocol": "^1.51.0", + "@vscode/debugprotocol": "^1.53.0", "eslint": "^8.8.0", "glob": "^7.2.0", "mocha": "^9.2.0", @@ -372,4 +372,4 @@ } ] } -} +} \ No newline at end of file diff --git a/src/debugProtocol.json b/src/debugProtocol.json index a000610..90a36a0 100644 --- a/src/debugProtocol.json +++ b/src/debugProtocol.json @@ -3830,6 +3830,10 @@ "type": "string", "description": "A string that should be used when comparing this item with other items. When `falsy` the label is used." }, + "detail": { + "type": "string", + "description": "A human-readable string with additional information about this item, like type or symbol information." + }, "type": { "$ref": "#/definitions/CompletionItemType", "description": "The item's type. Typically the client uses this information to render the item in the UI with an icon."