Skip to content

Commit b06df49

Browse files
committed
Add ideClient tag via bazel params
1 parent 0d220f2 commit b06df49

File tree

9 files changed

+220
-2
lines changed

9 files changed

+220
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ dist
66
.DS_Store
77
.bazelbsp
88
.bsp
9+
vscode-bazel-bsp-*.vsix

src/test-info/test-info.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ export class BuildTargetTestCaseInfo extends TestCaseInfo {
124124
}
125125
}
126126

127+
// Add the IDE tag (--define flag) to additionalBazelParams
128+
const ideTag = currentRun.getIdeTag()
129+
if (ideTag && ideTag.trim().length > 0) {
130+
if (bazelParams.additionalBazelParams) {
131+
bazelParams.additionalBazelParams += ` ${ideTag}`
132+
} else {
133+
bazelParams.additionalBazelParams = ideTag
134+
}
135+
}
136+
127137
const params = {
128138
targets: [this.target.id],
129139
originId: currentRun.originName,

src/test-runner/run-factory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {TestRunTracker} from './run-tracker'
77
import {BazelBSPBuildClient} from '../test-explorer/client'
88
import {CoverageTracker} from '../coverage-utils/coverage-tracker'
99
import {LanguageToolManager} from '../language-tools/manager'
10+
import {detectIdeClient} from '../utils/utils'
1011

1112
@Injectable()
1213
export class RunTrackerFactory {
@@ -37,6 +38,9 @@ export class RunTrackerFactory {
3738
languageToolManager: this.languageToolManager,
3839
})
3940

41+
const ideClient = detectIdeClient()
42+
requestTracker.setIdeTag(ideClient)
43+
4044
this.buildClient.registerOriginHandlers(originId, requestTracker)
4145
requestTracker.onDone(() =>
4246
this.buildClient.disposeOriginHandlers(originId)

src/test-runner/run-tracker.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export class TestRunTracker implements TaskOriginHandlers {
7272
private buildTaskTracker: TaskEventTracker = new TaskEventTracker()
7373
private debugInfo: DebugInfo | undefined
7474
private hasDebugSessionBeenInitiated = false
75+
private ideTag: string
7576

7677
constructor(params: RunTrackerParams) {
7778
this.allTests = new Map<TestItemType, TestCaseInfo[]>()
@@ -83,6 +84,7 @@ export class TestRunTracker implements TaskOriginHandlers {
8384
this.cancelToken = params.cancelToken
8485
this.coverageTracker = params.coverageTracker
8586
this.languageToolManager = params.languageToolManager
87+
this.ideTag = 'unknown'
8688

8789
this.prepareCurrentRun()
8890
this.prepareDebugInfo()
@@ -491,6 +493,23 @@ export class TestRunTracker implements TaskOriginHandlers {
491493
)
492494
}
493495
}
496+
497+
/**
498+
* Set the IDE tag to be used for this test run
499+
* @param ideClient IDE client identifier (e.g., 'vscode', 'cursor')
500+
*/
501+
public setIdeTag(ideClient: string): void {
502+
// Use Bazel's --define flag which is specifically designed for user-defined values
503+
this.ideTag = `--define=ide_client=${ideClient}`
504+
}
505+
506+
/**
507+
* Get the IDE tag for this test run
508+
* @returns The IDE client identifier
509+
*/
510+
public getIdeTag(): string {
511+
return this.ideTag
512+
}
494513
}
495514

496515
function formatTestResultMessage(

src/test/suite/run-factory.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {TestItemFactory} from '../../test-info/test-item-factory'
2222
import {CoverageTracker} from '../../coverage-utils/coverage-tracker'
2323
import {LanguageToolManager} from '../../language-tools/manager'
2424
import {SyncHintDecorationsManager} from '../../test-explorer/decorator'
25+
import * as utils from '../../utils/utils'
2526

2627
suite('Test Runner Factory', () => {
2728
let ctx: vscode.ExtensionContext
@@ -117,4 +118,25 @@ suite('Test Runner Factory', () => {
117118
assert.equal(registerHandlersStub.firstCall.args[1], runTracker)
118119
assert.ok(disposeHandlersStub.calledOnce)
119120
})
121+
122+
test('newRun sets IDE tag', async () => {
123+
const detectIdeClientStub = sandbox.stub(utils, 'detectIdeClient')
124+
detectIdeClientStub.returns('test-ide')
125+
126+
try {
127+
const roots: vscode.TestItem[] = []
128+
testCaseStore.testController.items.forEach(item => {
129+
roots.push(item)
130+
})
131+
const sampleToken = new vscode.CancellationTokenSource().token
132+
const runTracker = runFactory.newRun(
133+
new vscode.TestRunRequest(Array.from(roots)),
134+
sampleToken
135+
)
136+
assert.ok(detectIdeClientStub.calledOnce)
137+
assert.equal(runTracker.getIdeTag(), '--define=ide_client=test-ide')
138+
} finally {
139+
detectIdeClientStub.restore()
140+
}
141+
})
120142
})

src/test/suite/runner.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {CoverageTracker} from '../../coverage-utils/coverage-tracker'
3131
import {LanguageToolManager} from '../../language-tools/manager'
3232
import {SyncHintDecorationsManager} from '../../test-explorer/decorator'
3333
import * as settings from '../../utils/settings'
34+
import * as utils from '../../utils/utils'
3435

3536
suite('Test Runner', () => {
3637
let ctx: vscode.ExtensionContext
@@ -207,6 +208,9 @@ suite('Test Runner', () => {
207208
.stub(sampleConn, 'sendRequest')
208209
.returns(Promise.resolve(sampleResult))
209210

211+
// Mock the IDE tag detection
212+
sandbox.stub(utils, 'detectIdeClient').returns('cursor')
213+
210214
// Ensure run profile creation.
211215
await testRunner.onModuleInit()
212216
const runProfile = testRunner.runProfiles.get(
@@ -234,7 +238,7 @@ suite('Test Runner', () => {
234238
assert.ok(!callArgs[1].data.coverage)
235239
assert.strictEqual(
236240
callArgs[1].data.additionalBazelParams,
237-
'--my_flag_1 --my_flag_2'
241+
'--my_flag_1 --my_flag_2 --define=ide_client=cursor'
238242
)
239243
assert.strictEqual(callArgs[1].dataKind, TestParamsDataKind.BazelTest)
240244
}

src/test/suite/test-info.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,67 @@ suite('TestInfo', () => {
198198
const result = testInfo.prepareTestRunParams(currentRun)
199199
assert.equal(result, undefined)
200200
})
201+
202+
test('build target with IDE tag', async () => {
203+
const testItem = testController.createTestItem('sample', 'sample')
204+
const testInfo = new BuildTargetTestCaseInfo(testItem, sampleTarget)
205+
206+
// Test with IDE tag
207+
const currentRun = sandbox.createStubInstance(TestRunTracker)
208+
sandbox.stub(currentRun, 'originName').get(() => 'sample')
209+
currentRun.getRunProfileKind.returns(vscode.TestRunProfileKind.Run)
210+
currentRun.getIdeTag.returns('--define=ide_client=cursor')
211+
212+
const result = testInfo.prepareTestRunParams(currentRun)
213+
assert.deepStrictEqual(result, {
214+
arguments: [],
215+
environmentVariables: {},
216+
originId: 'sample',
217+
targets: [
218+
{
219+
uri: '//sample/target:test',
220+
},
221+
],
222+
workingDirectory: '',
223+
dataKind: TestParamsDataKind.BazelTest,
224+
data: {
225+
coverage: false,
226+
additionalBazelParams: '--define=ide_client=cursor',
227+
},
228+
})
229+
})
230+
231+
test('build target with IDE tag and debug flags', async () => {
232+
const testItem = testController.createTestItem('sample', 'sample')
233+
const testInfo = new BuildTargetTestCaseInfo(testItem, sampleTarget)
234+
235+
// Test with IDE tag and debug flags
236+
const currentRunWithDebug = sandbox.createStubInstance(TestRunTracker)
237+
sandbox.stub(currentRunWithDebug, 'originName').get(() => 'sample')
238+
currentRunWithDebug.getRunProfileKind.returns(
239+
vscode.TestRunProfileKind.Debug
240+
)
241+
currentRunWithDebug.getIdeTag.returns('--define=ide_client=vscode')
242+
currentRunWithDebug.getDebugBazelFlags.returns(['--flag1', '--flag2'])
243+
244+
const resultWithDebug = testInfo.prepareTestRunParams(currentRunWithDebug)
245+
assert.deepStrictEqual(resultWithDebug, {
246+
arguments: [],
247+
environmentVariables: {},
248+
originId: 'sample',
249+
targets: [
250+
{
251+
uri: '//sample/target:test',
252+
},
253+
],
254+
workingDirectory: '',
255+
dataKind: TestParamsDataKind.BazelTest,
256+
data: {
257+
coverage: false,
258+
additionalBazelParams: '--flag1 --flag2 --define=ide_client=vscode',
259+
},
260+
})
261+
})
201262
})
202263

203264
suite('Set display name', () => {

src/test/suite/utils.test.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sinon from 'sinon'
44
import {afterEach} from 'mocha'
55
import * as zlib from 'zlib'
66

7-
import {Deferred, Utils} from '../../utils/utils'
7+
import {Deferred, Utils, detectIdeClient} from '../../utils/utils'
88

99
suite('Utils Test Suite', () => {
1010
const sandbox = sinon.createSandbox()
@@ -119,6 +119,71 @@ suite('Utils Test Suite', () => {
119119
assert.ok(error instanceof Error)
120120
}
121121
})
122+
123+
test('detectIdeClient with different environments', async () => {
124+
const processEnv = process.env
125+
126+
const testCases = [
127+
{
128+
env: {
129+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/path/to/.vscode/remote-cli',
130+
__CFBundleIdentifier: '',
131+
},
132+
expected: 'vscode',
133+
name: 'VSCode remote',
134+
},
135+
{
136+
env: {
137+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
138+
__CFBundleIdentifier: 'com.microsoft.VSCode',
139+
},
140+
expected: 'vscode',
141+
name: 'VSCode local',
142+
},
143+
{
144+
env: {
145+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/path/to/.cursor/remote-cli',
146+
__CFBundleIdentifier: '',
147+
},
148+
expected: 'cursor',
149+
name: 'Cursor remote',
150+
},
151+
{
152+
env: {
153+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
154+
__CFBundleIdentifier: 'com.todesktop.230313mzl4w4u92',
155+
},
156+
expected: 'cursor',
157+
name: 'Cursor local',
158+
},
159+
{
160+
env: {
161+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
162+
__CFBundleIdentifier: 'com.microsoft.VSCodeInsiders',
163+
},
164+
expected: 'vscode-insiders',
165+
name: 'VSCode Insiders local',
166+
},
167+
{
168+
env: {
169+
PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
170+
__CFBundleIdentifier: '',
171+
},
172+
expected: 'unknown',
173+
name: 'Unknown IDE',
174+
},
175+
]
176+
177+
try {
178+
for (const {env, expected, name} of testCases) {
179+
process.env = env
180+
const result = detectIdeClient()
181+
assert.strictEqual(result, expected, `Failed: ${name}`)
182+
}
183+
} finally {
184+
process.env = processEnv
185+
}
186+
})
122187
})
123188

124189
suite('Deferred Promise Test Suite', () => {

src/utils/utils.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,35 @@ export class Deferred<T> {
104104
})
105105
}
106106
}
107+
108+
/**
109+
* Detect which IDE client is being used.
110+
* @returns {string} The detected IDE client identifier
111+
*/
112+
export function detectIdeClient(): string {
113+
const path = process.env.PATH || ''
114+
const cfBundleId = process.env.__CFBundleIdentifier || ''
115+
116+
// Cursor detection
117+
if (
118+
(path.includes('.cursor') && path.includes('remote-cli')) ||
119+
cfBundleId === 'com.todesktop.230313mzl4w4u92'
120+
) {
121+
return 'cursor'
122+
}
123+
124+
// VS Code detection
125+
if (
126+
(path.includes('.vscode') && path.includes('remote-cli')) ||
127+
cfBundleId === 'com.microsoft.VSCode'
128+
) {
129+
return 'vscode'
130+
}
131+
132+
// VS Code Insiders detection
133+
if (cfBundleId === 'com.microsoft.VSCodeInsiders') {
134+
return 'vscode-insiders'
135+
}
136+
137+
return 'unknown'
138+
}

0 commit comments

Comments
 (0)