Skip to content

Commit d73a20e

Browse files
Add global configuration for justMyCode (microsoft#91)
* Aff configuration * Read just my code from settings too * fix tests * fix lint
1 parent 117bc23 commit d73a20e

File tree

8 files changed

+93
-80
lines changed

8 files changed

+93
-80
lines changed

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@
7979
}
8080
]
8181
},
82+
"configuration": {
83+
"properties": {
84+
"debugpy.debugJustMyCode": {
85+
"default": true,
86+
"description": "%debugpy.debugJustMyCode%",
87+
"scope": "resource",
88+
"type": "boolean"
89+
}
90+
},
91+
"title": "Python Debugger",
92+
"type": "object"
93+
},
8294
"debuggers": [
8395
{
8496
"configurationAttributes": {

package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"debugpy.command.debugInTerminal.title": "Debug Python File",
33
"debugpy.command.clearCacheAndReload.title": "Clear Cache and Reload Window",
4-
"debugpy.command.viewOutput.title": "Show Output"
4+
"debugpy.command.viewOutput.title": "Show Output",
5+
"debugpy.debugJustMyCode": "When debugging only step through user-written code. Disable this to allow stepping into library code."
56
}

src/extension/debugger/configuration/resolvers/attach.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CancellationToken, Uri, WorkspaceFolder } from 'vscode';
77
import { getOSType, OSType } from '../../../common/platform';
88
import { AttachRequestArguments, DebugOptions, PathMapping } from '../../../types';
99
import { BaseConfigurationResolver } from './base';
10+
import { getConfiguration } from '../../../common/vscodeapi';
1011

1112
export class AttachConfigurationResolver extends BaseConfigurationResolver<AttachRequestArguments> {
1213
public async resolveDebugConfigurationWithSubstitutedVariables(
@@ -42,16 +43,12 @@ export class AttachConfigurationResolver extends BaseConfigurationResolver<Attac
4243
debugConfiguration.host = 'localhost';
4344
}
4445
if (debugConfiguration.justMyCode === undefined) {
45-
// Populate justMyCode using debugStdLib
46-
debugConfiguration.justMyCode = !debugConfiguration.debugStdLib;
46+
debugConfiguration.justMyCode = getConfiguration('debugpy').get<boolean>('debugJustMyCode', true);
4747
}
4848
debugConfiguration.showReturnValue = debugConfiguration.showReturnValue !== false;
4949
// Pass workspace folder so we can get this when we get debug events firing.
5050
debugConfiguration.workspaceFolder = workspaceFolder ? workspaceFolder.fsPath : undefined;
5151
const debugOptions = debugConfiguration.debugOptions!;
52-
if (!debugConfiguration.justMyCode) {
53-
AttachConfigurationResolver.debugOption(debugOptions, DebugOptions.DebugStdLib);
54-
}
5552
if (debugConfiguration.django) {
5653
AttachConfigurationResolver.debugOption(debugOptions, DebugOptions.Django);
5754
}

src/extension/debugger/configuration/resolvers/launch.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { DebugOptions, DebugPurpose, LaunchRequestArguments } from '../../../typ
1111
import { resolveVariables } from '../utils/common';
1212
import { BaseConfigurationResolver } from './base';
1313
import { getDebugEnvironmentVariables, getProgram } from './helper';
14+
import { getConfiguration } from '../../../common/vscodeapi';
1415

1516
export class LaunchConfigurationResolver extends BaseConfigurationResolver<LaunchRequestArguments> {
1617
public async resolveDebugConfiguration(
@@ -102,15 +103,11 @@ export class LaunchConfigurationResolver extends BaseConfigurationResolver<Launc
102103
debugConfiguration.debugOptions = [];
103104
}
104105
if (debugConfiguration.justMyCode === undefined) {
105-
// Populate justMyCode using debugStdLib
106-
debugConfiguration.justMyCode = !debugConfiguration.debugStdLib;
106+
debugConfiguration.justMyCode = getConfiguration('debugpy').get<boolean>('debugJustMyCode', true);
107107
}
108108
// Pass workspace folder so we can get this when we get debug events firing.
109109
debugConfiguration.workspaceFolder = workspaceFolder ? workspaceFolder.fsPath : undefined;
110110
const debugOptions = debugConfiguration.debugOptions!;
111-
if (!debugConfiguration.justMyCode) {
112-
LaunchConfigurationResolver.debugOption(debugOptions, DebugOptions.DebugStdLib);
113-
}
114111
if (debugConfiguration.stopOnEntry) {
115112
LaunchConfigurationResolver.debugOption(debugOptions, DebugOptions.StopOnEntry);
116113
}

src/test/unittest/adapter/factory.unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ suite('Debugging - Adapter Factory', () => {
126126
assert.deepStrictEqual(descriptor, debugExecutable);
127127
});
128128

129-
test.only('Display a message if no python interpreter is set', async () => {
129+
test('Display a message if no python interpreter is set', async () => {
130130
getActiveEnvironmentPathStub.resolves(undefined);
131131
const session = createSession({});
132132
const promise = factory.createDebugAdapterDescriptor(session, nodeExecutable);

src/test/unittest/configuration/resolvers/attach.unit.test.ts

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@
66
import { expect } from 'chai';
77
import * as TypeMoq from 'typemoq';
88
import * as sinon from 'sinon';
9-
import { DebugConfiguration, DebugConfigurationProvider, TextDocument, TextEditor, Uri, WorkspaceFolder } from 'vscode';
9+
import {
10+
DebugConfiguration,
11+
DebugConfigurationProvider,
12+
TextDocument,
13+
TextEditor,
14+
Uri,
15+
WorkspaceConfiguration,
16+
WorkspaceFolder,
17+
} from 'vscode';
1018
import { PYTHON_LANGUAGE } from '../../../../extension/common/constants';
1119
import { getInfoPerOS } from './common';
1220
import { AttachRequestArguments, DebugOptions } from '../../../../extension/types';
@@ -34,6 +42,7 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
3442
let getActiveTextEditorStub: sinon.SinonStub;
3543
let getWorkspaceFoldersStub: sinon.SinonStub;
3644
let getOSTypeStub: sinon.SinonStub;
45+
let getConfigurationStub: sinon.SinonStub;
3746
const debugOptionsAvailable = getAvailableOptions();
3847

3948
setup(() => {
@@ -42,6 +51,8 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
4251
getOSTypeStub = sinon.stub(platform, 'getOSType');
4352
getWorkspaceFoldersStub = sinon.stub(vscodeapi, 'getWorkspaceFolders');
4453
getOSTypeStub.returns(osType);
54+
getConfigurationStub = sinon.stub(vscodeapi, 'getConfiguration');
55+
getConfigurationStub.withArgs('debugpy').returns(createMoqConfiguration(true));
4556
});
4657

4758
teardown(() => {
@@ -54,6 +65,14 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
5465
return folder.object;
5566
}
5667

68+
function createMoqConfiguration(justMyCode: boolean) {
69+
const debugpySettings = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
70+
debugpySettings
71+
.setup((p) => p.get<boolean>('debugJustMyCode', TypeMoq.It.isAny()))
72+
.returns(() => justMyCode);
73+
return debugpySettings.object;
74+
}
75+
5776
function setupActiveEditor(fileName: string | undefined, languageId: string) {
5877
if (fileName) {
5978
const textEditor = TypeMoq.Mock.ofType<TextEditor>();
@@ -493,67 +512,52 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
493512
const testsForJustMyCode = [
494513
{
495514
justMyCode: false,
496-
debugStdLib: true,
515+
justMyCodeSetting: true,
497516
expectedResult: false,
498517
},
499518
{
500519
justMyCode: false,
501-
debugStdLib: false,
520+
justMyCodeSetting: false,
502521
expectedResult: false,
503522
},
504-
{
505-
justMyCode: false,
506-
debugStdLib: undefined,
507-
expectedResult: false,
508-
},
509-
{
510-
justMyCode: true,
511-
debugStdLib: false,
512-
expectedResult: true,
513-
},
514523
{
515524
justMyCode: true,
516-
debugStdLib: true,
525+
justMyCodeSetting: false,
517526
expectedResult: true,
518527
},
519528
{
520529
justMyCode: true,
521-
debugStdLib: undefined,
522-
expectedResult: true,
523-
},
524-
{
525-
justMyCode: undefined,
526-
debugStdLib: false,
530+
justMyCodeSetting: true,
527531
expectedResult: true,
528532
},
529533
{
530534
justMyCode: undefined,
531-
debugStdLib: true,
535+
justMyCodeSetting: false,
532536
expectedResult: false,
533537
},
534538
{
535539
justMyCode: undefined,
536-
debugStdLib: undefined,
540+
justMyCodeSetting: true,
537541
expectedResult: true,
538542
},
539543
];
540-
test('Ensure justMyCode property is correctly derived from debugStdLib', async () => {
541-
const activeFile = 'xyz.py';
542-
const workspaceFolder = createMoqWorkspaceFolder(__dirname);
543-
setupActiveEditor(activeFile, PYTHON_LANGUAGE);
544-
const defaultWorkspace = path.join('usr', 'desktop');
545-
setupWorkspaces([defaultWorkspace]);
544+
testsForJustMyCode.forEach(async (testParams) => {
545+
test('Ensure justMyCode property is correctly derived from global settings', async () => {
546+
const activeFile = 'xyz.py';
547+
const workspaceFolder = createMoqWorkspaceFolder(__dirname);
548+
setupActiveEditor(activeFile, PYTHON_LANGUAGE);
549+
const defaultWorkspace = path.join('usr', 'desktop');
550+
setupWorkspaces([defaultWorkspace]);
546551

547-
const debugOptions = debugOptionsAvailable
548-
.slice()
549-
.concat(DebugOptions.Jinja, DebugOptions.Sudo) as DebugOptions[];
552+
const debugOptions = debugOptionsAvailable
553+
.slice()
554+
.concat(DebugOptions.Jinja, DebugOptions.Sudo) as DebugOptions[];
550555

551-
testsForJustMyCode.forEach(async (testParams) => {
556+
getConfigurationStub.withArgs('debugpy').returns(createMoqConfiguration(testParams.justMyCodeSetting));
552557
const debugConfig = await resolveDebugConfiguration(workspaceFolder, {
553558
...attach,
554559
debugOptions,
555560
justMyCode: testParams.justMyCode,
556-
debugStdLib: testParams.debugStdLib,
557561
});
558562
expect(debugConfig).to.have.property('justMyCode', testParams.expectedResult);
559563
});

src/test/unittest/configuration/resolvers/launch.unit.test.ts

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@
66
import { expect } from 'chai';
77
import * as TypeMoq from 'typemoq';
88
import * as sinon from 'sinon';
9-
import { DebugConfiguration, DebugConfigurationProvider, TextDocument, TextEditor, Uri, WorkspaceFolder } from 'vscode';
9+
import {
10+
DebugConfiguration,
11+
DebugConfigurationProvider,
12+
TextDocument,
13+
TextEditor,
14+
Uri,
15+
WorkspaceConfiguration,
16+
WorkspaceFolder,
17+
} from 'vscode';
1018
import { PYTHON_LANGUAGE } from '../../../../extension/common/constants';
1119
import { LaunchConfigurationResolver } from '../../../../extension/debugger/configuration/resolvers/launch';
1220
import { getInfoPerOS } from './common';
@@ -31,6 +39,7 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
3139
let getInterpreterDetailsStub: sinon.SinonStub;
3240
let getEnvFileStub: sinon.SinonStub;
3341
let getDebugEnvironmentVariablesStub: sinon.SinonStub;
42+
let getConfigurationStub: sinon.SinonStub;
3443

3544
setup(() => {
3645
getActiveTextEditorStub = sinon.stub(vscodeapi, 'getActiveTextEditor');
@@ -40,6 +49,8 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
4049
getInterpreterDetailsStub = sinon.stub(pythonApi, 'getInterpreterDetails');
4150
getEnvFileStub = sinon.stub(settings, 'getEnvFile');
4251
getDebugEnvironmentVariablesStub = sinon.stub(helper, 'getDebugEnvironmentVariables');
52+
getConfigurationStub = sinon.stub(vscodeapi, 'getConfiguration');
53+
getConfigurationStub.withArgs('debugpy').returns(createMoqConfiguration(true));
4354
});
4455

4556
teardown(() => {
@@ -52,6 +63,14 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
5263
return folder.object;
5364
}
5465

66+
function createMoqConfiguration(justMyCode: boolean) {
67+
const debugpySettings = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
68+
debugpySettings
69+
.setup((p) => p.get<boolean>('debugJustMyCode', TypeMoq.It.isAny()))
70+
.returns(() => justMyCode);
71+
return debugpySettings.object;
72+
}
73+
5574
function getClientOS() {
5675
return osType === platform.OSType.Windows ? 'windows' : 'unix';
5776
}
@@ -726,11 +745,7 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
726745
expect(debugConfig).to.have.property('redirectOutput', true);
727746
expect(debugConfig).to.have.property('justMyCode', false);
728747
expect(debugConfig).to.have.property('debugOptions');
729-
const expectedOptions = [
730-
DebugOptions.DebugStdLib,
731-
DebugOptions.ShowReturnValue,
732-
DebugOptions.RedirectOutput,
733-
];
748+
const expectedOptions = [DebugOptions.ShowReturnValue, DebugOptions.RedirectOutput];
734749
if (osType === platform.OSType.Windows) {
735750
expectedOptions.push(DebugOptions.FixFilePathCase);
736751
}
@@ -740,60 +755,45 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
740755
const testsForJustMyCode = [
741756
{
742757
justMyCode: false,
743-
debugStdLib: true,
744-
expectedResult: false,
745-
},
746-
{
747-
justMyCode: false,
748-
debugStdLib: false,
758+
justMyCodeSetting: true,
749759
expectedResult: false,
750760
},
751761
{
752762
justMyCode: false,
753-
debugStdLib: undefined,
763+
justMyCodeSetting: false,
754764
expectedResult: false,
755765
},
756766
{
757767
justMyCode: true,
758-
debugStdLib: false,
759-
expectedResult: true,
760-
},
761-
{
762-
justMyCode: true,
763-
debugStdLib: true,
768+
justMyCodeSetting: false,
764769
expectedResult: true,
765770
},
766771
{
767772
justMyCode: true,
768-
debugStdLib: undefined,
773+
justMyCodeSetting: true,
769774
expectedResult: true,
770775
},
771776
{
772777
justMyCode: undefined,
773-
debugStdLib: false,
774-
expectedResult: true,
775-
},
776-
{
777-
justMyCode: undefined,
778-
debugStdLib: true,
778+
justMyCodeSetting: false,
779779
expectedResult: false,
780780
},
781781
{
782782
justMyCode: undefined,
783-
debugStdLib: undefined,
783+
justMyCodeSetting: true,
784784
expectedResult: true,
785785
},
786786
];
787-
test('Ensure justMyCode property is correctly derived from debugStdLib', async () => {
788-
const pythonPath = `PythonPath_${new Date().toString()}`;
789-
const workspaceFolder = createMoqWorkspaceFolder(__dirname);
790-
const pythonFile = 'xyz.py';
791-
setupIoc(pythonPath);
792-
setupActiveEditor(pythonFile, PYTHON_LANGUAGE);
793-
testsForJustMyCode.forEach(async (testParams) => {
787+
testsForJustMyCode.forEach(async (testParams) => {
788+
test('Ensure justMyCode property is correctly derived from global settings', async () => {
789+
const pythonPath = `PythonPath_${new Date().toString()}`;
790+
const workspaceFolder = createMoqWorkspaceFolder(__dirname);
791+
const pythonFile = 'xyz.py';
792+
setupIoc(pythonPath);
793+
setupActiveEditor(pythonFile, PYTHON_LANGUAGE);
794+
getConfigurationStub.withArgs('debugpy').returns(createMoqConfiguration(testParams.justMyCodeSetting));
794795
const debugConfig = await resolveDebugConfiguration(workspaceFolder, {
795796
...launch,
796-
debugStdLib: testParams.debugStdLib,
797797
justMyCode: testParams.justMyCode,
798798
});
799799
expect(debugConfig).to.have.property('justMyCode', testParams.expectedResult);
@@ -930,6 +930,7 @@ getInfoPerOS().forEach(([osName, osType, path]) => {
930930
request: requestType,
931931
type: 'python',
932932
name: '',
933+
justMyCode: false,
933934
...settings,
934935
};
935936
const workspaceFolder = createMoqWorkspaceFolder(__dirname);

src/test/unittest/extensionInit.unit.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ suite('Debugging - register Debugging', () => {
6868
sinon.assert.calledWithExactly(registerCommandStub, Commands.ClearStorage, sinon.match.any);
6969
expect(registerCommandStub.callCount).to.be.equal(5);
7070
});
71+
7172
test('Activation will register the Debug adapter factories', async () => {
7273
registerDebugger(context.object);
7374

0 commit comments

Comments
 (0)