Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitbake recipe view #60

Merged
merged 18 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
77acf71
Feature: Add Bitbake recipe view
deribaucourt Nov 8, 2023
7de4110
Feature: Update recipe view when recipes are added or dropped
deribaucourt Nov 8, 2023
869275d
Feature: Add context menu commands to recipes view
deribaucourt Nov 8, 2023
e3c2355
Refactor: Rename BitbakeRecipe to BitbakeRecipeTreeItem
deribaucourt Nov 8, 2023
03ed59e
Feature: Add a tree item view for adding recipes to the workspace
deribaucourt Nov 8, 2023
8317c3a
Fix: Only show bitbake view when the extension is active
deribaucourt Nov 8, 2023
5c0665e
Feature: Add icons to bitbake commands
deribaucourt Nov 8, 2023
b9da397
Feature: Add icon to rescan the project in the bitbake view
deribaucourt Nov 8, 2023
c40a1f4
Refactor: Move Bitbake Scan Types into common library
deribaucourt Nov 8, 2023
faeb24b
Feature: Send Bitbake project scan results to client
deribaucourt Nov 8, 2023
a30a21f
Feature: Add bitbake recipe source in recipe view
deribaucourt Nov 8, 2023
0ee9e12
Feature: Add appends and include files to the tree view
deribaucourt Nov 8, 2023
4599ab1
Fix: Add a problem matcher for "Unable to parse" errors
deribaucourt Nov 9, 2023
b0bca74
Fix: Filter bitbake appends if the version does not match
deribaucourt Nov 9, 2023
dcf9120
Test: Add unit tests for BitbakeRecipesView
deribaucourt Nov 9, 2023
f26822a
Feature: Add warning when recipe not found in tree view
deribaucourt Nov 9, 2023
9facb00
Fix: Use the bitbakeRecipesView variable
deribaucourt Nov 10, 2023
99d3ca3
Fix: Generate build dir before parse tests
deribaucourt Nov 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions __mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const languages = {
onDidChangeActiveTextEditor: jest.fn(),
showInformationMessage: jest.fn(),
createWebviewPanel: jest.fn(),
registerTreeDataProvider: jest.fn(),
createTreeView: jest.fn(),
};

const workspace = {
Expand Down Expand Up @@ -105,6 +107,13 @@ const languages = {
Default: 0,
};

const TreeItem = jest.fn();
const TreeItemCollapsibleState = {
None: 0,
Collapsed: 1,
Expanded: 2,
};

export = {
ThemeColor,
CodeLens,
Expand All @@ -131,4 +140,6 @@ const languages = {
TestRunRequest,
ViewColumn,
QuickPickItemKind,
TreeItem,
TreeItemCollapsibleState
};
55 changes: 55 additions & 0 deletions client/images/yocto-view-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 90 additions & 9 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@
"message": 4
}
},
{
"name": "bitbake-UnableToParse",
"source": "bitbake",
"owner": "bitbake",
"fileLocation": [
"autoDetect",
"${cwd}"
],
"pattern": {
"regexp": "^ERROR: (Unable to parse) (.+)$",
"file": 2,
"message": 1,
"kind": "File"
}
},
{
"name": "bitbake-Variable",
"source": "bitbake",
Expand Down Expand Up @@ -194,17 +209,20 @@
{
"command": "bitbake.rescan-project",
"title": "BitBake: Rescan Project",
"description": "This command rescans the bitbake project."
"description": "This command rescans the bitbake project.",
"icon": "$(refresh)"
},
{
"command": "bitbake.build-recipe",
"title": "BitBake: Build recipe",
"description": "Build a recipe or an image."
"description": "Build a recipe or an image.",
"icon": "$(gear)"
},
{
"command": "bitbake.clean-recipe",
"title": "BitBake: Clean recipe",
"description": "Clean a recipe or an image (bitbake -c clean)."
"description": "Clean a recipe or an image (bitbake -c clean).",
"icon": "$(exclude)"
},
{
"command": "bitbake.run-task",
Expand All @@ -214,20 +232,39 @@
{
"command": "bitbake.drop-recipe",
"title": "BitBake: Drop a recipe from the active workspace",
"description": "Stop watching or suggesting a recipe in bitbake commands."
"description": "Stop watching or suggesting a recipe in bitbake commands.",
"icon": "$(close)"
},
{
"command": "bitbake.watch-recipe",
"title": "BitBake: Add a recipe to the active workspace",
"description": "Start watching or suggesting a recipe in bitbake commands.",
"enablement": "false"
"description": "Start watching or suggesting a recipe in bitbake commands."
},
{
"command": "bitbake.parse-recipes",
"title": "BitBake: Parse all recipes",
"description": "This command runs bitbake in parse-only mode."
}
],
"viewsContainers": {
"activitybar": [
{
"id": "bitbakeView",
"title": "Bitbake",
"icon": "images/yocto-view-icon.svg"
}
]
},
"views": {
"bitbakeView": [
{
"id": "bitbakeRecipes",
"name": "Recipes",
"contextualTitle": "Recipes Explorer",
"when": "resourceLangId == bitbake"
WilsonZiweiWang marked this conversation as resolved.
Show resolved Hide resolved
}
]
},
"submenus": [
{
"id": "bitbake/main",
Expand All @@ -238,15 +275,15 @@
"bitbake/main": [
{
"command": "bitbake.clean-recipe",
"group": "bitbake_recipe"
"group": "bitbake_recipe@1"
},
{
"command": "bitbake.build-recipe",
"group": "bitbake_recipe"
"group": "bitbake_recipe@0"
},
{
"command": "bitbake.run-task",
"group": "bitbake_recipe"
"group": "bitbake_recipe@2"
}
],
"explorer/context": [
Expand All @@ -269,6 +306,50 @@
"group": "bitbake",
"when": "resourceLangId == bitbake"
}
],
"view/title": [
{
"command": "bitbake.rescan-project",
"group": "navigation@0",
"when": "view == bitbakeRecipes"
}
],
"view/item/context": [
{
"command": "bitbake.clean-recipe",
"group": "bitbake_recipe@1",
"when": "view == bitbakeRecipeCtx"
},
{
"command": "bitbake.build-recipe",
"group": "bitbake_recipe@0",
"when": "viewItem == bitbakeRecipeCtx"
},
{
"command": "bitbake.run-task",
"group": "bitbake_recipe@2",
"when": "viewItem == bitbakeRecipeCtx"
},
{
"command": "bitbake.drop-recipe",
"group": "bitbake_recipe@3",
"when": "viewItem == bitbakeRecipeCtx"
},
{
"command": "bitbake.build-recipe",
"group": "inline@0",
"when": "viewItem == bitbakeRecipeCtx"
},
{
"command": "bitbake.clean-recipe",
"group": "inline@1",
"when": "viewItem == bitbakeRecipeCtx"
},
{
"command": "bitbake.drop-recipe",
"group": "inline@2",
"when": "viewItem == bitbakeRecipeCtx"
}
]
}
},
Expand Down
71 changes: 71 additions & 0 deletions client/src/__tests__/unit-tests/ui/bitbake-recipes-view.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* --------------------------------------------------------------------------------------------
* 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 { type BitbakeRecipeTreeItem, BitbakeRecipesView } from '../../../ui/BitbakeRecipesView'
import { BitbakeWorkspace } from '../../../ui/BitbakeWorkspace'
import { BitBakeProjectScannerClient } from '../../../language/BitbakeProjectScannerClient'
import { type LanguageClient } from 'vscode-languageclient/node'

jest.mock('vscode')

describe('BitbakeDriver Recipes View', () => {
it('should list recipes', (done) => {
const bitbakeWorkspace = new BitbakeWorkspace()
bitbakeWorkspace.addActiveRecipe('base-files')

const clientMock: LanguageClient = {
onNotification: jest.fn()
} as any
const contextMock: vscode.ExtensionContext = {
subscriptions: {
push: jest.fn()
}
} as any

const bitbakeProjectScannerClient = new BitBakeProjectScannerClient(clientMock)
bitbakeProjectScannerClient.bitbakeScanResult = {
recipes: [
{
name: 'base-files',
path: {
root: '/',
dir: '/home/user/yocto/poky/meta/recipes-core/base-files',
base: 'base-files_3.0.14',
ext: '.bb',
name: 'base-files'
},
appends: [
{
root: '/',
dir: '/home/user/yocto/poky/meta/recipes-core/base-files',
base: 'base-files_%',
ext: '.bbappend',
name: 'base-files'
}
]
}
],
includes: []
}

vscode.window.registerTreeDataProvider = jest.fn().mockImplementation(
async (viewId: string, treeDataProvider: vscode.TreeDataProvider<BitbakeRecipeTreeItem>): Promise<void> => {
const rootTreeItem = await treeDataProvider.getChildren(undefined)
expect(rootTreeItem).toBeDefined()
expect(rootTreeItem?.length).toStrictEqual(2)
const recipeItem = (rootTreeItem as BitbakeRecipeTreeItem[])[0]
expect(recipeItem.label).toStrictEqual('base-files')

const filesItems = await treeDataProvider.getChildren(recipeItem)
expect(filesItems).toBeDefined()
expect(filesItems?.length).toStrictEqual(2)
done()
})

const bitbakeRecipesView = new BitbakeRecipesView(bitbakeWorkspace, bitbakeProjectScannerClient)
bitbakeRecipesView.registerView(contextMock)
})
})
8 changes: 8 additions & 0 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ import { BitbakeDriver } from './lib/src/BitbakeDriver'
import { BitbakeTaskProvider } from './ui/BitbakeTaskProvider'
import { registerBitbakeCommands } from './ui/BitbakeCommands'
import { BitbakeWorkspace } from './ui/BitbakeWorkspace'
import { BitbakeRecipesView } from './ui/BitbakeRecipesView'
import { BitBakeProjectScannerClient } from './language/BitbakeProjectScannerClient'

let client: LanguageClient
const bitbakeDriver: BitbakeDriver = new BitbakeDriver()
let bitbakeTaskProvider: BitbakeTaskProvider
let taskProvider: vscode.Disposable
const bitbakeWorkspace: BitbakeWorkspace = new BitbakeWorkspace()
export let bitbakeExtensionContext: vscode.ExtensionContext
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let bitbakeRecipesView: BitbakeRecipesView | undefined

function loadLoggerSettings (): void {
logger.level = vscode.workspace.getConfiguration('bitbake').get('loggingLevel') ?? 'info'
Expand Down Expand Up @@ -51,6 +55,10 @@ export async function activate (context: vscode.ExtensionContext): Promise<void>

const notificationManager = new ClientNotificationManager(client, context.globalState)
context.subscriptions.push(...notificationManager.buildHandlers())
const bitBakeProjectScannerClient = new BitBakeProjectScannerClient(client)
context.subscriptions.push(...bitBakeProjectScannerClient.buildHandlers())
bitbakeRecipesView = new BitbakeRecipesView(bitbakeWorkspace, bitBakeProjectScannerClient)
bitbakeRecipesView.registerView(context)

// Handle settings change for bitbake driver
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((event) => {
Expand Down
37 changes: 37 additions & 0 deletions client/src/language/BitbakeProjectScannerClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* --------------------------------------------------------------------------------------------
* 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 type * as vscode from 'vscode'
import { type LanguageClient } from 'vscode-languageclient/node'
import { type BitbakeScanResult } from '../lib/src/types/BitbakeScanResult'
import EventEmitter from 'events'
import { logger } from '../lib/src/utils/OutputLogger'

/// Keeps track of the bitbake scan results from the language server
export class BitBakeProjectScannerClient {
bitbakeScanResult: BitbakeScanResult = { recipes: [], includes: [] }
private readonly client: LanguageClient
onChange: EventEmitter = new EventEmitter()

constructor (client: LanguageClient) {
this.client = client
}

buildHandlers (): vscode.Disposable[] {
const handlers = [
this.bitbakeScanHandler()
]

return handlers
}

private bitbakeScanHandler (): vscode.Disposable {
return this.client.onNotification('bitbake/scanReady', (scanResults: BitbakeScanResult) => {
this.bitbakeScanResult = scanResults
this.onChange.emit('scanReady', scanResults)
logger.info('Bitbake scan results received from language server')
})
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Eugen Wiens. All rights reserved.
* Copyright (c) 2023 Savoir-faire Linux. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */

Expand All @@ -26,3 +26,8 @@ export interface ElementInfo {
overlayes?: PathInfo[]
version?: string
}

export interface BitbakeScanResult {
recipes: ElementInfo[]
includes: ElementInfo[]
}
Loading