Skip to content

Commit

Permalink
Resolve based on open files
Browse files Browse the repository at this point in the history
  • Loading branch information
mnoah1 committed Oct 10, 2024
1 parent f20826c commit d3e838c
Show file tree
Hide file tree
Showing 10 changed files with 337 additions and 48 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
"Do not install BSP server if not already present."
],
"description": "Installation behavior for the build server."
},
"bazelbsp.autoExpandTarget": {
"type": "boolean",
"default": "true",
"description": "Find all tests within open files, without waiting for the file's target to be expanded in the Test Explorer."
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/language-tools/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ export class BaseLanguageTools implements LanguageTools {
/**
* No support for individual test cases or test file identification.
* @param document URI of the document to be analyzed for test cases.
* @returns Result always contains isTestFile value of true, and no test cases.
* @returns Result always contains isTestFile value of false, and no test cases.
*/
async getDocumentTestCases(
document: vscode.Uri,
workspaceRoot: string
): Promise<TestFileContents> {
return {
// Do not filter out any files.
isTestFile: true,
isTestFile: false,
// No test case discovery.
testCases: [],
}
Expand Down
9 changes: 9 additions & 0 deletions src/language-tools/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,13 @@ export class LanguageToolManager {
}
return this.baseLanguageTools
}

getLanguageToolsForFile(document: vscode.TextDocument): LanguageTools {
if (document.languageId === 'python') {
return this.pythonLanguageTools
} else if (document.languageId === 'java') {
return this.javaLanguageTools
}
return this.baseLanguageTools
}
}
87 changes: 87 additions & 0 deletions src/test-explorer/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ export class TestResolver implements OnModuleInit, vscode.Disposable {
const directories = new Map<string, vscode.TestItem>()
const buildFileName = getExtensionSetting(SettingName.BUILD_FILE_NAME)
parentTest.children.replace([])
this.store.clearTargetIdentifiers()

result.targets.forEach(target => {
if (!target.capabilities.canTest) return

Expand All @@ -211,6 +213,7 @@ export class TestResolver implements OnModuleInit, vscode.Disposable {
buildFileUri
)
relevantParent.children.add(newTest)
this.store.setTargetIdentifier(target.id, newTest)
})

// If no test items were added, show the getting started message as a test message overlaid on the .bazelproject file.
Expand All @@ -235,6 +238,88 @@ export class TestResolver implements OnModuleInit, vscode.Disposable {
// Replace all children with the newly returned test cases.
this.condenseTestItems(parentTest)
updateDescription(parentTest)

await this.resolveOpenSourceFiles()
}

/**
* Kick off resolution of test items for files that are currently open, and watch for newly opened files.
* This allows test cases to appear without the user having to expand the target's test explorer node.
*/
private async resolveOpenSourceFiles() {
const autoExpandTarget = getExtensionSetting(SettingName.AUTO_EXPAND_TARGET)
// When disabled, tests are discovered as the test explorer tree is expanded.
if (!autoExpandTarget) return

for (const doc of vscode.workspace.textDocuments) {
// Discovery within currently open documents.
await this.expandTargetsForDocument(doc)
}

this.ctx.subscriptions.push(
vscode.workspace.onDidOpenTextDocument(async doc => {
// Discovery within newly opened documents.
await this.expandTargetsForDocument(doc)
})
)
}

/**
* Finds the corresponding target for a given document, if a file's target is not yet known.
* The target's test cases will then be resolved and available in test explorer.
* @param doc for which to find the target.
*/
private async expandTargetsForDocument(doc: vscode.TextDocument) {
if (doc.uri.scheme !== 'file') return

// Avoid checking files that are already known, or not test files.
if (this.store.knownFiles.has(doc.uri.toString())) return
const tools = this.languageToolManager.getLanguageToolsForFile(doc)
const docInfo = await tools.getDocumentTestCases(
doc.uri,
this.repoRoot ?? ''
)
if (!docInfo.isTestFile) return

this.store.knownFiles.add(doc.uri.toString())
const conn = await this.buildServer.getConnection()
const params: bsp.InverseSourcesParams = {
textDocument: {
uri: doc.uri.toString(),
},
}
let result: bsp.InverseSourcesResult | undefined
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: `Getting target for ${path.basename(doc.fileName)}.`,
cancellable: true,
},
async (progress, token) => {
result = await conn.sendRequest(
bsp.BuildTargetInverseSources.type,
params,
token
)
}
)

if (!result) {
// TODO(IDE-1203): Add more guidance to update their sync scope.
this.outputChannel.appendLine(`Target not in scope for ${doc.fileName}.`)
return
}

for (const target of result.targets) {
const targetItem = this.store.getTargetIdentifier(target)
if (targetItem) {
await this.resolveHandler(targetItem)
} else {
this.outputChannel.appendLine(
`Couldn't find a matching test item for ${target.uri}.`
)
}
}
}

/**
Expand Down Expand Up @@ -264,6 +349,7 @@ export class TestResolver implements OnModuleInit, vscode.Disposable {

const directories = new Map<string, vscode.TestItem>()
parentTest.children.replace([])
parentTest.canResolveChildren = false
const allDocumentTestItems: vscode.TestItem[] = []
result.items.forEach(target => {
target.sources.forEach(source => {
Expand All @@ -290,6 +376,7 @@ export class TestResolver implements OnModuleInit, vscode.Disposable {
parentTarget,
source
)
this.store.knownFiles.add(source.uri)

relevantParent.children.add(newTest)
allDocumentTestItems.push(newTest)
Expand Down
24 changes: 24 additions & 0 deletions src/test-explorer/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
TEST_CONTROLLER_TOKEN,
} from '../custom-providers'
import {TestCaseInfo} from '../test-info/test-info'
import {BuildTargetIdentifier} from 'src/bsp/bsp'

export class TestCaseStore implements OnModuleInit, vscode.Disposable {
@Inject(EXTENSION_CONTEXT_TOKEN) private readonly ctx: vscode.ExtensionContext
Expand All @@ -15,10 +16,14 @@ export class TestCaseStore implements OnModuleInit, vscode.Disposable {

// Watcher to update a test item's children. Key corresponds to the test item ID.
testItemWatchers: Map<string, vscode.FileSystemWatcher>
knownFiles: Set<string>
private targetIdentifiers: Map<string, vscode.TestItem>

constructor() {
this.testCaseMetadata = new WeakMap<vscode.TestItem, TestCaseInfo>()
this.testItemWatchers = new Map()
this.targetIdentifiers = new Map<string, vscode.TestItem>()
this.knownFiles = new Set<string>()
}

onModuleInit() {
Expand Down Expand Up @@ -59,4 +64,23 @@ export class TestCaseStore implements OnModuleInit, vscode.Disposable {
}
clear(parentTest)
}

setTargetIdentifier(
targetIdentifier: BuildTargetIdentifier,
item: vscode.TestItem
) {
const key = JSON.stringify(targetIdentifier)
this.targetIdentifiers.set(key, item)
}

getTargetIdentifier(
targetIdentifier: BuildTargetIdentifier
): vscode.TestItem | undefined {
const key = JSON.stringify(targetIdentifier)
return this.targetIdentifiers.get(key)
}

clearTargetIdentifiers() {
this.targetIdentifiers.clear()
}
}
2 changes: 1 addition & 1 deletion src/test/suite/language-tools/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ suite('Base Language Tools', () => {
vscode.Uri.parse('file:///repo/root/sample/my_test.py'),
'/repo/root/'
)
assert.strictEqual(result.isTestFile, true)
assert.strictEqual(result.isTestFile, false)
assert.strictEqual(result.testCases.length, 0)
})

Expand Down
21 changes: 21 additions & 0 deletions src/test/suite/language-tools/manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,25 @@ suite('Language Tools Manager', () => {
const result = languageTools.getLanguageTools(target)
assert.strictEqual(result.constructor.name, 'BaseLanguageTools')
})

test('get tools for file, python', async () => {
const result = languageTools.getLanguageToolsForFile({
languageId: 'python',
} as any)
assert.strictEqual(result.constructor.name, 'PythonLanguageTools')
})

test('get tools for file, java', async () => {
const result = languageTools.getLanguageToolsForFile({
languageId: 'java',
} as any)
assert.strictEqual(result.constructor.name, 'JavaLanguageTools')
})

test('get tools for file, other', async () => {
const result = languageTools.getLanguageToolsForFile({
languageId: 'other',
} as any)
assert.strictEqual(result.constructor.name, 'BaseLanguageTools')
})
})
Loading

0 comments on commit d3e838c

Please sign in to comment.