diff --git a/src/extension/debugger/inlineValue/pythonInlineValueProvider.ts b/src/extension/debugger/inlineValue/pythonInlineValueProvider.ts index aac0d2e9..ae836d2b 100644 --- a/src/extension/debugger/inlineValue/pythonInlineValueProvider.ts +++ b/src/extension/debugger/inlineValue/pythonInlineValueProvider.ts @@ -65,9 +65,17 @@ export class PythonInlineValueProvider implements InlineValuesProvider { 'self', ]; - const pythonVariables: any[] = variablesRequest.variables + let includeTypes = ['int', 'float', 'str', 'list', 'dict', 'tuple', 'set', 'bool']; + + const pythonVariables = variablesRequest.variables .filter((variable: any) => variable.type) - .map((variable: any) => variable.name); + .reduce((acc: { [key: string]: any }, variable: any) => { + acc[variable.name] = { + type: variable.type, + variablesReference: variable.variablesReference, + }; + return acc; + }, {}); let variableRegex = new RegExp( '(?:[a-zA-Z_][a-zA-Z0-9_]*\\.)*' + //match any number of variable names separated by '.' @@ -91,13 +99,26 @@ export class PythonInlineValueProvider implements InlineValuesProvider { if (pythonKeywords.includes(varName)) { continue; } - if (pythonVariables.includes(varName.split('.')[0])) { + let baseVarName = varName.split('.')[0]; + if (pythonVariables.hasOwnProperty(baseVarName)) { if (varName.includes('.')) { - const rng = new Range(l, match.index, l, match.index + varName.length); - allValues.push(new InlineValueEvaluatableExpression(rng, varName)); + //Find variable name in the variable children + let foundVariable = ( + await customRequest('variables', { + variablesReference: pythonVariables[baseVarName].variablesReference, + }) + ).variables.find((variable: any) => variable.evaluateName === varName); + //Check the type of the variable before adding to the inline values + if (foundVariable && includeTypes.includes(foundVariable.type)) { + const rng = new Range(l, match.index, l, match.index + varName.length); + allValues.push(new InlineValueEvaluatableExpression(rng, varName)); + } } else { - const rng = new Range(l, match.index, l, match.index + varName.length); - allValues.push(new InlineValueVariableLookup(rng, varName, false)); + //Check the type of the variable before adding to the inline values + if (includeTypes.includes(pythonVariables[baseVarName].type)) { + const rng = new Range(l, match.index, l, match.index + varName.length); + allValues.push(new InlineValueVariableLookup(rng, varName, false)); + } } } } diff --git a/src/extension/extensionInit.ts b/src/extension/extensionInit.ts index 08db7f16..976e3405 100644 --- a/src/extension/extensionInit.ts +++ b/src/extension/extensionInit.ts @@ -215,7 +215,7 @@ export async function registerDebugger(context: IExtensionContext): Promise { - if (event.affectsConfiguration('debugpy')) { + if (event.affectsConfiguration('debugpy.showPythonInlineValues')) { const showInlineValues = getConfiguration('debugpy').get('showPythonInlineValues', false); if (!showInlineValues) { registerInlineValuesProviderDisposable.dispose(); diff --git a/src/test/unittest/inlineValue/pythonInlineValueProvider.unit.test.ts b/src/test/unittest/inlineValue/pythonInlineValueProvider.unit.test.ts index 9cbdf287..53ca560c 100644 --- a/src/test/unittest/inlineValue/pythonInlineValueProvider.unit.test.ts +++ b/src/test/unittest/inlineValue/pythonInlineValueProvider.unit.test.ts @@ -202,14 +202,35 @@ suite('Debugging - pythonInlineProvider', () => { }); test('ProvideInlineValues function should return all the vars in the python file with self in class', async () => { + customRequestStub + .withArgs('variables', sinon.match.any) + .onFirstCall() + .resolves({ + variables: [ + { + name: 'self', + value: '<__main__.Person object at 0x10b223310>', + type: 'Person', + evaluateName: 'self', + variablesReference: 5, + }, + ], + }); customRequestStub.withArgs('variables', sinon.match.any).resolves({ variables: [ { - name: 'self', - value: '<__main__.Person object at 0x10b223310>', - type: 'Person', - evaluateName: 'self', - variablesReference: 5, + name: 'name', + value: "'John'", + type: 'str', + evaluateName: 'self.name', + variablesReference: 0, + }, + { + name: 'age', + value: '25', + type: 'int', + evaluateName: 'self.age', + variablesReference: 0, }, ], }); @@ -278,15 +299,46 @@ suite('Debugging - pythonInlineProvider', () => { expect(result).to.deep.equal(expected); }); - test('ProvideInlineValues function should return all the vars in the python file with class variables', async () => { + test('ProvideInlineValues function should return the vars in the python file with readable class variables', async () => { + customRequestStub + .withArgs('variables', sinon.match.any) + .onFirstCall() + .resolves({ + variables: [ + { + name: 'person1', + value: '<__main__.Person object at 0x1085c92b0>', + type: 'Person', + evaluateName: 'person1', + variablesReference: 7, + }, + ], + }); customRequestStub.withArgs('variables', sinon.match.any).resolves({ variables: [ { - name: 'person1', - value: '<__main__.Person object at 0x1085c92b0>', - type: 'Person', - evaluateName: 'person1', - variablesReference: 7, + name: 'age', + value: '30', + type: 'int', + evaluateName: 'person1.age', + variablesReference: 0, + }, + { + name: 'id', + value: '1', + type: 'int', + evaluateName: 'person1.id', + variablesReference: 0, + }, + { + name: 'name', + value: "'John Doe'", + type: 'str', + evaluateName: 'person1.name', + variablesReference: 0, + presentationHint: { + attributes: ['rawString'], + }, }, ], }); @@ -299,33 +351,6 @@ suite('Debugging - pythonInlineProvider', () => { const result = await inlineValueProvider.provideInlineValues(document, viewPort, context); const expected = [ - { - range: { - c: { - c: 9, - e: 0, - }, - e: { - c: 9, - e: 7, - }, - }, - variableName: 'person1', - caseSensitiveLookup: false, - }, - { - range: { - c: { - c: 10, - e: 0, - }, - e: { - c: 10, - e: 13, - }, - }, - expression: 'person1.greet', - }, { range: { c: {