Skip to content

Commit

Permalink
Feat: Add diagnostics for embedded Bash and Python
Browse files Browse the repository at this point in the history
  • Loading branch information
idillon-sfl committed Dec 16, 2023
1 parent b0dd7b0 commit eb81f87
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 1 deletion.
14 changes: 14 additions & 0 deletions client/src/language/EmbeddedLanguageDocsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ export default class EmbeddedLanguageDocsManager {
return embeddedLanguageDocs?.[languageType]
}

getOriginalUri (embeddedLanguageDocUri: Uri): Uri | undefined {
let originalUri: Uri | undefined
this.embeddedLanguageDocsInfos.forEach((embeddedLanguageDocs, stringUri) => {
if (
embeddedLanguageDocs.bash?.uri.toString() === embeddedLanguageDocUri.toString() ||
embeddedLanguageDocs.python?.uri.toString() === embeddedLanguageDocUri.toString()
) {
originalUri = Uri.parse(stringUri)
}
})
return originalUri
}

private createEmbeddedLanguageDocUri (embeddedLanguageDoc: EmbeddedLanguageDoc): Uri | undefined {
if (this.storagePath === undefined) {
return undefined
Expand Down Expand Up @@ -129,6 +142,7 @@ export default class EmbeddedLanguageDocsManager {
}
try {
await workspace.fs.writeFile(uri, Buffer.from(embeddedLanguageDoc.content))
await workspace.openTextDocument(uri)
} catch (err) {
logger.error(`Failed to create embedded document: ${err as any}`)
}
Expand Down
67 changes: 67 additions & 0 deletions client/src/language/diagnosticsSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2023 Savoir-faire Linux. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */

import * as vscode from 'vscode'

import { getOriginalDocRange } from './utils'
import { embeddedLanguageDocsManager } from './EmbeddedLanguageDocsManager'
import { type EmbeddedLanguageType } from '../lib/src/types/embedded-languages'

const diagnosticCollections = {
bash: vscode.languages.createDiagnosticCollection('bitbake-bash'),
python: vscode.languages.createDiagnosticCollection('bitbake-python')
}

export const updateDiagnostics = async (uri: vscode.Uri): Promise<void> => {
if (!uri.path.endsWith('.py') && !uri.path.endsWith('.sh')) {
return
}
const originalUri = embeddedLanguageDocsManager.getOriginalUri(uri)
if (originalUri === undefined) {
return
}
const originalTextDocument = await vscode.workspace.openTextDocument(originalUri)
await Promise.all([
setEmbeddedLanguageDocDiagnostics(originalTextDocument, 'bash'),
setEmbeddedLanguageDocDiagnostics(originalTextDocument, 'python')
])
}

const setEmbeddedLanguageDocDiagnostics = async (
originalTextDocument: vscode.TextDocument,
embeddedLanguageType: EmbeddedLanguageType
): Promise<void> => {
const embeddedLanguageDocInfos = embeddedLanguageDocsManager.getEmbeddedLanguageDocInfos(
originalTextDocument.uri.toString(),
embeddedLanguageType
)
if (embeddedLanguageDocInfos?.uri === undefined) {
return
}
const embeddedLanguageDoc = await vscode.workspace.openTextDocument(embeddedLanguageDocInfos.uri.fsPath)
const dirtyDiagnostics = vscode.languages.getDiagnostics(embeddedLanguageDocInfos.uri)
const cleanDiagnostics: vscode.Diagnostic[] = []
dirtyDiagnostics.forEach((diagnostic) => {
if (diagnostic.range === undefined) {
cleanDiagnostics.push(diagnostic)
}
const newRange = getOriginalDocRange(
originalTextDocument,
embeddedLanguageDoc,
embeddedLanguageDocInfos.characterIndexes,
diagnostic.range
)
if (newRange === undefined) {
return
}
const newDiagnostic = {
...diagnostic,
range: newRange
}
cleanDiagnostics.push(newDiagnostic)
})
const diagnosticCollection = diagnosticCollections[embeddedLanguageType]
diagnosticCollection.set(originalTextDocument.uri, cleanDiagnostics)
}
10 changes: 9 additions & 1 deletion client/src/language/languageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
workspace,
type ExtensionContext,
window,
commands
commands,
languages
} from 'vscode'

import {
Expand All @@ -24,6 +25,7 @@ import { requestsManager } from './RequestManager'
import { embeddedLanguageDocsManager } from './EmbeddedLanguageDocsManager'
import { logger } from '../lib/src/utils/OutputLogger'
import { NotificationMethod, type NotificationParams } from '../lib/src/types/notifications'
import { updateDiagnostics } from './diagnosticsSupport'

export async function activateLanguageServer (context: ExtensionContext): Promise<LanguageClient> {
const serverModule = context.asAbsolutePath(path.join('server', 'server.js'))
Expand Down Expand Up @@ -75,6 +77,12 @@ export async function activateLanguageServer (context: ExtensionContext): Promis
}
}

languages.onDidChangeDiagnostics(e => {
e.uris.forEach(uri => {
void updateDiagnostics(uri)
})
})

if (context.storageUri?.fsPath === undefined) {
logger.error('Failed to get storage path')
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
python () {
error()
}
44 changes: 44 additions & 0 deletions integration-tests/src/tests/diagnostics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2023 Savoir-faire Linux. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */

import * as assert from 'assert'
import * as vscode from 'vscode'
import path from 'path'

suite('Bitbake Diagnostics Test Suite', () => {
const filePath = path.resolve(__dirname, '../../project-folder/sources/meta-fixtures/diagnostics.bb')
const docUri = vscode.Uri.parse(`file://${filePath}`)

suiteSetup(async function (this: Mocha.Context) {
this.timeout(100000)
const vscodeBitbake = vscode.extensions.getExtension('yocto-project.yocto-bitbake')
if (vscodeBitbake === undefined) {
assert.fail('Bitbake extension is not available')
}
await vscodeBitbake.activate()
await vscode.workspace.openTextDocument(docUri)
})

test('Diagnostics', async () => {
await new Promise<vscode.Diagnostic[]>((resolve, reject) => {
let nbChanges = 0
vscode.languages.onDidChangeDiagnostics((e) => {
const diagnostics = vscode.languages.getDiagnostics(docUri)
if (diagnostics.length > 0) {
resolve(diagnostics)
}
if (nbChanges > 2) {
reject(new Error('Waited too long for diagnostics'))
}
nbChanges++
})
}).then((diagnostics) => {
assert.strictEqual(diagnostics.length, 1)
assert.strictEqual(diagnostics[0].source, 'Pylance')
}).catch((err) => {
assert.fail(err)
})
}).timeout(300000)
})

0 comments on commit eb81f87

Please sign in to comment.