Skip to content

Commit c348467

Browse files
author
Kartik Raj
committed
Support diagnostics in a untrusted workspace
1 parent 685ed99 commit c348467

File tree

10 files changed

+54
-9
lines changed

10 files changed

+54
-9
lines changed

src/client/activation/activationManager.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,7 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
9797
}
9898
await sendActivationTelemetry(this.fileSystem, this.workspaceService, resource);
9999
await Promise.all(this.activationServices.map((item) => item.activate(resource)));
100-
if (this.workspaceService.isTrusted) {
101-
await this.appDiagnostics.performPreStartupHealthCheck(resource);
102-
}
100+
await this.appDiagnostics.performPreStartupHealthCheck(resource);
103101
}
104102

105103
public async initialize(): Promise<void> {

src/client/application/diagnostics/applicationDiagnostics.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { inject, injectable, named } from 'inversify';
77
import { DiagnosticSeverity } from 'vscode';
8+
import { IWorkspaceService } from '../../common/application/types';
89
import { isTestExecution, STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
910
import { IOutputChannel, Resource } from '../../common/types';
1011
import { IServiceContainer } from '../../ioc/types';
@@ -26,7 +27,11 @@ export class ApplicationDiagnostics implements IApplicationDiagnostics {
2627
if (isTestExecution()) {
2728
return;
2829
}
29-
const services = this.serviceContainer.getAll<IDiagnosticsService>(IDiagnosticsService);
30+
let services = this.serviceContainer.getAll<IDiagnosticsService>(IDiagnosticsService);
31+
const workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
32+
if (!workspaceService.isTrusted) {
33+
services = services.filter((item) => item.runInUntrustedWorkspace);
34+
}
3035
// Perform these validation checks in the foreground.
3136
await this.runDiagnostics(
3237
services.filter((item) => !item.runInBackground),

src/client/application/diagnostics/base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export abstract class BaseDiagnosticsService implements IDiagnosticsService, IDi
3535
@unmanaged() protected serviceContainer: IServiceContainer,
3636
@unmanaged() disposableRegistry: IDisposableRegistry,
3737
@unmanaged() public readonly runInBackground: boolean = false,
38+
@unmanaged() public readonly runInUntrustedWorkspace: boolean = false,
3839
) {
3940
this.filterService = serviceContainer.get<IDiagnosticFilterService>(IDiagnosticFilterService);
4041
disposableRegistry.push(this);

src/client/application/diagnostics/checks/envPathVariable.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ export class EnvironmentPathVariableDiagnosticsService extends BaseDiagnosticsSe
4343
@inject(IServiceContainer) serviceContainer: IServiceContainer,
4444
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
4545
) {
46-
super([DiagnosticCodes.InvalidEnvironmentPathVariableDiagnostic], serviceContainer, disposableRegistry, true);
46+
super(
47+
[DiagnosticCodes.InvalidEnvironmentPathVariableDiagnostic],
48+
serviceContainer,
49+
disposableRegistry,
50+
true,
51+
true,
52+
);
4753
this.platform = this.serviceContainer.get<IPlatformService>(IPlatformService);
4854
this.messageService = serviceContainer.get<IDiagnosticHandlerService<MessageCommandPrompt>>(
4955
IDiagnosticHandlerService,

src/client/application/diagnostics/checks/pylanceDefault.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class PylanceDefaultDiagnosticService extends BaseDiagnosticsService {
4040
protected readonly messageService: IDiagnosticHandlerService<MessageCommandPrompt>,
4141
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
4242
) {
43-
super([DiagnosticCodes.PylanceDefaultDiagnostic], serviceContainer, disposableRegistry, true);
43+
super([DiagnosticCodes.PylanceDefaultDiagnostic], serviceContainer, disposableRegistry, true, true);
4444

4545
this.initialMementoValue = this.context.globalState.get(EXTENSION_VERSION_MEMENTO);
4646
}

src/client/application/diagnostics/checks/switchToDefaultLS.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class SwitchToDefaultLanguageServerDiagnosticService extends BaseDiagnost
3838
protected readonly messageService: IDiagnosticHandlerService<MessageCommandPrompt>,
3939
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
4040
) {
41-
super([DiagnosticCodes.JediPython27NotSupportedDiagnostic], serviceContainer, disposableRegistry, true);
41+
super([DiagnosticCodes.JediPython27NotSupportedDiagnostic], serviceContainer, disposableRegistry, true, true);
4242
}
4343

4444
public diagnose(resource: Resource): Promise<IDiagnostic[]> {

src/client/application/diagnostics/checks/upgradeCodeRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export class UpgradeCodeRunnerDiagnosticService extends BaseDiagnosticsService {
4343
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
4444
@inject(IExtensions) private readonly extensions: IExtensions,
4545
) {
46-
super([DiagnosticCodes.UpgradeCodeRunnerDiagnostic], serviceContainer, disposableRegistry, true);
46+
super([DiagnosticCodes.UpgradeCodeRunnerDiagnostic], serviceContainer, disposableRegistry, true, true);
4747
this.workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
4848
}
4949

src/client/application/diagnostics/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const IDiagnosticsService = Symbol('IDiagnosticsService');
2727

2828
export interface IDiagnosticsService {
2929
readonly runInBackground: boolean;
30+
readonly runInUntrustedWorkspace: boolean;
3031
diagnose(resource: Resource): Promise<IDiagnostic[]>;
3132
canHandle(diagnostic: IDiagnostic): Promise<boolean>;
3233
handle(diagnostics: IDiagnostic[]): Promise<void>;

src/test/activation/activationManager.unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ suite('Activation Manager', () => {
159159
appDiagnostics
160160
.setup((a) => a.performPreStartupHealthCheck(resource))
161161
.returns(() => Promise.resolve())
162-
.verifiable(typemoq.Times.never());
162+
.verifiable(typemoq.Times.once());
163163

164164
managerTest = new ExtensionActivationManagerTest(
165165
[instance(activationService1), instance(activationService2)],

src/test/application/diagnostics/applicationDiagnostics.unit.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
ISourceMapSupportService,
1818
} from '../../../client/application/diagnostics/types';
1919
import { IApplicationDiagnostics } from '../../../client/application/types';
20+
import { IWorkspaceService } from '../../../client/common/application/types';
2021
import { STANDARD_OUTPUT_CHANNEL } from '../../../client/common/constants';
2122
import { IOutputChannel } from '../../../client/common/types';
2223
import { createDeferred, createDeferredFromPromise } from '../../../client/common/utils/async';
@@ -30,6 +31,7 @@ suite('Application Diagnostics - ApplicationDiagnostics', () => {
3031
let lsNotSupportedCheck: typemoq.IMock<IDiagnosticsService>;
3132
let pythonInterpreterCheck: typemoq.IMock<IDiagnosticsService>;
3233
let outputChannel: typemoq.IMock<IOutputChannel>;
34+
let workspaceService: typemoq.IMock<IWorkspaceService>;
3335
let appDiagnostics: IApplicationDiagnostics;
3436
const oldValueOfVSC_PYTHON_UNIT_TEST = process.env.VSC_PYTHON_UNIT_TEST;
3537
const oldValueOfVSC_PYTHON_CI_TEST = process.env.VSC_PYTHON_CI_TEST;
@@ -44,14 +46,20 @@ suite('Application Diagnostics - ApplicationDiagnostics', () => {
4446
lsNotSupportedCheck.setup((service) => service.runInBackground).returns(() => false);
4547
pythonInterpreterCheck = typemoq.Mock.ofType<IDiagnosticsService>();
4648
pythonInterpreterCheck.setup((service) => service.runInBackground).returns(() => false);
49+
pythonInterpreterCheck.setup((service) => service.runInUntrustedWorkspace).returns(() => false);
4750
outputChannel = typemoq.Mock.ofType<IOutputChannel>();
51+
workspaceService = typemoq.Mock.ofType<IWorkspaceService>();
52+
workspaceService.setup((w) => w.isTrusted).returns(() => true);
4853

4954
serviceContainer
5055
.setup((d) => d.getAll(typemoq.It.isValue(IDiagnosticsService)))
5156
.returns(() => [envHealthCheck.object, lsNotSupportedCheck.object, pythonInterpreterCheck.object]);
5257
serviceContainer
5358
.setup((d) => d.get(typemoq.It.isValue(IOutputChannel), typemoq.It.isValue(STANDARD_OUTPUT_CHANNEL)))
5459
.returns(() => outputChannel.object);
60+
serviceContainer
61+
.setup((d) => d.get(typemoq.It.isValue(IWorkspaceService)))
62+
.returns(() => workspaceService.object);
5563

5664
appDiagnostics = new ApplicationDiagnostics(serviceContainer.object, outputChannel.object);
5765
});
@@ -95,6 +103,29 @@ suite('Application Diagnostics - ApplicationDiagnostics', () => {
95103
pythonInterpreterCheck.verifyAll();
96104
});
97105

106+
test('When running in a untrusted workspace skip diagnosing validation checks which do not support it', async () => {
107+
workspaceService.reset();
108+
workspaceService.setup((w) => w.isTrusted).returns(() => false);
109+
envHealthCheck
110+
.setup((e) => e.diagnose(typemoq.It.isAny()))
111+
.returns(() => Promise.resolve([]))
112+
.verifiable(typemoq.Times.once());
113+
lsNotSupportedCheck
114+
.setup((p) => p.diagnose(typemoq.It.isAny()))
115+
.returns(() => Promise.resolve([]))
116+
.verifiable(typemoq.Times.once());
117+
pythonInterpreterCheck
118+
.setup((p) => p.diagnose(typemoq.It.isAny()))
119+
.returns(() => Promise.resolve([]))
120+
.verifiable(typemoq.Times.never());
121+
122+
await appDiagnostics.performPreStartupHealthCheck(undefined);
123+
124+
envHealthCheck.verifyAll();
125+
lsNotSupportedCheck.verifyAll();
126+
pythonInterpreterCheck.verifyAll();
127+
});
128+
98129
test('Performing Pre Startup Health Check must handles all validation checks only once either in background or foreground', async () => {
99130
const diagnostic: IDiagnostic = {
100131
code: 'Error' as any,
@@ -215,9 +246,12 @@ suite('Application Diagnostics - ApplicationDiagnostics', () => {
215246
const foreGroundService = mock(InvalidPythonInterpreterService);
216247
const backGroundService = mock(EnvironmentPathVariableDiagnosticsService);
217248
const svcContainer = mock(ServiceContainer);
249+
const workspaceService = mock<IWorkspaceService>();
218250
const foreGroundDeferred = createDeferred<IDiagnostic[]>();
219251
const backgroundGroundDeferred = createDeferred<IDiagnostic[]>();
220252

253+
when(svcContainer.get<IWorkspaceService>(IWorkspaceService)).thenReturn(workspaceService);
254+
when(workspaceService.isTrusted).thenReturn(true);
221255
when(svcContainer.getAll<IDiagnosticsService>(IDiagnosticsService)).thenReturn([
222256
instance(foreGroundService),
223257
instance(backGroundService),

0 commit comments

Comments
 (0)