Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
"code analysis"
],
"activationEvents": [
"onCommand:codechecker.backend.reloadMetadata",
"onView:codechecker.views.overview",
"onFileSystem:file"
"onStartupFinished"
],
"main": "./dist/extension.js",
"contributes": {
Expand Down
55 changes: 44 additions & 11 deletions src/backend/executor/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ import { NotificationType } from '../../editor/notifications';
import { Editor } from '../../editor';
import { SidebarContainer } from '../../sidebar';
import { ReportTreeItem } from '../../sidebar/views';
import {
COMPILE_COMMANDS_JSON,
getCompilationDatabasePath,
getOutputFolder,
isSupportedFile } from '../../utils/files';
import { state } from '../../utils/state';

// Structure:
// CodeChecker analyzer version: \n {"base_package_version": "M.m.p", ...}
Expand Down Expand Up @@ -116,8 +122,10 @@ export class ExecutorBridge implements Disposable {
ExtensionApi.executorManager
));

this.updateCompilationDatabasePaths();
this.checkVersion();
if (state.workspaceSupported) {
this.updateCompilationDatabasePaths();
this.checkVersion();
}
}

dispose() {
Expand Down Expand Up @@ -250,7 +258,18 @@ export class ExecutorBridge implements Disposable {
} else if (files.length === 0) {
// FIXME: Add a way to analyze all open workspaces, or a selected one
this._bridgeMessages.fire('>>> Using CodeChecker\'s built-in compilation database resolver\n');
args.push(workspace.workspaceFolders[0].uri.fsPath);
let analysisPath;
const ccDbFolder = getCompilationDatabasePath();
const outputFolder = getOutputFolder();
if (ccDbFolder !== undefined) {
analysisPath = path.join(ccDbFolder, COMPILE_COMMANDS_JSON);
} else if (outputFolder !== undefined) {
analysisPath = path.join(outputFolder, COMPILE_COMMANDS_JSON);
} else {
const workspaceFolder = workspace.workspaceFolders[0].uri.fsPath;
analysisPath = path.join(workspaceFolder, '.codechecker');
}
args.push(analysisPath);
} else if (files.length === 1) {
this._bridgeMessages.fire('>>> Using CodeChecker\'s built-in compilation database resolver\n');
args.push(files[0].fsPath);
Expand Down Expand Up @@ -387,13 +406,13 @@ export class ExecutorBridge implements Disposable {
public async analyzeCurrentFile() {
const currentFile = window.activeTextEditor?.document.uri;

if (currentFile !== undefined) {
if (currentFile !== undefined && isSupportedFile(currentFile)) {
await this.analyzeFile(currentFile);
}
}

public async analyzeFile(file: Uri) {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || !await this.checkVersion()) {
return;
}

Expand All @@ -411,7 +430,7 @@ export class ExecutorBridge implements Disposable {
}

public async analyzeProject() {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || !await this.checkVersion()) {
return;
}

Expand All @@ -431,9 +450,15 @@ export class ExecutorBridge implements Disposable {
}

public async getFileAnalysisStatus() {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || !await this.checkVersion()) {
return;
}

const fileUri = window.activeTextEditor?.document.uri;
if (!isSupportedFile(fileUri)) {
return;
}

if (this.checkedVersion < [ 6, 27, 0 ]) {
const statusNode = SidebarContainer.reportsView.getNodeById('statusItem');
statusNode?.setLabelAndIcon('Status report requires CodeChecker 6.27.0 or higher.');
Expand All @@ -442,7 +467,6 @@ export class ExecutorBridge implements Disposable {

const ccPath = getConfigAndReplaceVariables('codechecker.executor', 'executablePath') || 'CodeChecker';
const reportsFolder = this.getReportsFolder();
const fileUri = window.activeTextEditor?.document.uri;
const fsPath = fileUri?.fsPath;

const statusArgs = [
Expand Down Expand Up @@ -516,6 +540,7 @@ export class ExecutorBridge implements Disposable {
analyzerStatuses.push(existingStatusNode);
} else {
existingStatusNode.iconPath = new ThemeIcon(iconname);
analyzerStatuses.push(existingStatusNode);
}
}
}
Expand All @@ -529,6 +554,9 @@ export class ExecutorBridge implements Disposable {
} else if (failed > 0) {
statusNode?.setLabelAndIcon('Analysis failed',
new ThemeIcon('error', new ThemeColor('charts.red')));
} else if (missing > 0 && outdated === 0 && uptodate === 0) {
statusNode?.setLabelAndIcon('Analysis is missing',
new ThemeIcon('error', new ThemeColor('charts.red')));
} else if (outdated === 0 && failed === 0) {
statusNode?.setLabelAndIcon('Analysis is up-to-date',
new ThemeIcon('check', new ThemeColor('charts.green')));
Expand Down Expand Up @@ -579,7 +607,7 @@ export class ExecutorBridge implements Disposable {
}

public async runLog(buildCommand?: string) {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || !await this.checkVersion()) {
return;
}

Expand All @@ -599,7 +627,7 @@ export class ExecutorBridge implements Disposable {
}

public async reloadCheckerData() {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || !await this.checkVersion()) {
return;
}

Expand Down Expand Up @@ -642,7 +670,12 @@ export class ExecutorBridge implements Disposable {
}

public async parseMetadata(...files: Uri[]) {
if (!await this.checkVersion()) {
if (!state.workspaceSupported || files.length === 0 || !await this.checkVersion()) {
return;
}

if (!files.find(uri => isSupportedFile(uri))) {
ExtensionApi.diagnostics.fireDiagnosticsUpdate();
return;
}

Expand Down
7 changes: 6 additions & 1 deletion src/backend/processor/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class DiagnosticsApi {
return undefined;
}

public fireDiagnosticsUpdate() {
this._diagnosticsUpdated.fire();
}

public setSelectedEntry(position?: {file: string, idx: number}) {
if (position) {
const activeFile = this.getFileDiagnostics(Uri.file(position.file)) ?? [];
Expand Down Expand Up @@ -88,7 +92,8 @@ export class DiagnosticsApi {
return;
}

ExtensionApi.executorBridge.parseMetadata(...filesToLoad.map(file => Uri.file(file)))
ExtensionApi.executorBridge.parseMetadata(...filesToLoad
.map(file => Uri.file(file)))
.catch((err: any) => console.log(`Internal error in reloadDiagnostics: ${err}`));
}

Expand Down
2 changes: 1 addition & 1 deletion src/editor/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class DiagnosticRenderer {
if (this.customSeverities && this.customSeverities[severity]) {
const severityString = this.customSeverities[severity];

if (typeof severityString === 'string' && this._severityMap[severityString.toLowerCase()]) {
if (typeof severityString === 'string' && this._severityMap[severityString.toLowerCase()] !== undefined) {
return this._severityMap[severityString.toLowerCase()];
} else {
Editor.loggerPanel.window.appendLine(
Expand Down
3 changes: 2 additions & 1 deletion src/editor/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ExtensionContext, Uri, commands, window, workspace } from 'vscode';
import { ExtensionApi } from '../backend';
import { Editor } from './editor';
import { NotificationType } from './notifications';
import { state } from '../utils/state';

export class FolderInitializer {
constructor(_ctx: ExtensionContext) {
Expand All @@ -27,7 +28,7 @@ export class FolderInitializer {
async showDialog() {
const workspaceFolder = workspace.workspaceFolders?.length && workspace.workspaceFolders[0].uri;

if (!workspaceFolder) {
if (!workspaceFolder || !state.workspaceSupported) {
return;
}

Expand Down
12 changes: 8 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import * as vscode from 'vscode';
import { ExtensionApi } from './backend';
import { Editor } from './editor';
import { SidebarContainer } from './sidebar';
import { checkWorkspace } from './utils/files';

export interface CodeCheckerExtension {
extensionApi: typeof ExtensionApi,
sidebarContainer: typeof SidebarContainer,
editor: typeof Editor
}

export function activate(context: vscode.ExtensionContext): CodeCheckerExtension {
export async function activate(context: vscode.ExtensionContext): Promise<CodeCheckerExtension> {
// Backend must be initialized before the frontend
ExtensionApi.init(context);
Editor.init(context);
SidebarContainer.init(context);

if (await checkWorkspace()) {
ExtensionApi.init(context);
Editor.init(context);
SidebarContainer.init(context);
}

console.log('Extension "codechecker" activated');

Expand Down
19 changes: 16 additions & 3 deletions src/sidebar/views/reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { ExtensionApi } from '../../backend';
import { DiagnosticReport } from '../../backend/types';
import { SidebarContainer } from '../sidebar_container';
import { isSupportedFile } from '../../utils/files';

export class ReportTreeItem extends TreeItem {
parent: ReportTreeItem | undefined;
Expand Down Expand Up @@ -378,13 +379,25 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {

// Get root level items.
getRootItems(): ReportTreeItem[] | undefined {
if (!this.currentEntryList?.length) {
if (!isSupportedFile(this.currentFile)) {
const statusNode = SidebarContainer.reportsView.getNodeById('statusItem');
statusNode?.setLabelAndIcon('Not in compilation database',
new ThemeIcon('question', new ThemeColor('charts.orange')));
if (statusNode !== undefined) {
statusNode.setLabelAndIcon('Not supported by codechecker',
new ThemeIcon('question', new ThemeColor('charts.orange')));
// statusNode.children = [];
statusNode.collapsibleState = TreeItemCollapsibleState.None;
const rootNode = statusNode.parent;
if (rootNode !== undefined) {
rootNode.children = [ statusNode ];
}
}
return statusNode ? [ statusNode ] : undefined;
}

if (this.currentEntryList === undefined) {
return undefined;
}

const severityItems: { [key: string]: TreeDiagnosticReport[] } = {};
for (const [idx, entry] of this.currentEntryList.entries()) {
const severity = entry.severity || 'UNSPECIFIED';
Expand Down
54 changes: 54 additions & 0 deletions src/utils/files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Uri, workspace } from 'vscode';
import { state } from './state';
import { getConfigAndReplaceVariables } from './config';

const EXTENSIONS = [
'.c',
'.cc',
'.cpp',
'.cxx'
];

export const COMPILE_COMMANDS_JSON = 'compile_commands.json';

export function isSupportedFile(uri: Uri | undefined): boolean {
if (uri === undefined) {
return false;
}

return EXTENSIONS.find(ext => uri.path.endsWith(ext)) !== undefined;
}

export async function isSupportedWorkspace() {
const supported = await workspace.findFiles(
`**/*{${EXTENSIONS.join(',')}}`,
'**/{node_modules,.git}/**',
1
);

return supported.length > 0;
}

export async function checkWorkspace() {
if (workspace.name === undefined) {
state.workspaceSupported = false;
console.log('No open workspace.');
return false;
}
const supported = await isSupportedWorkspace();
if (supported) {
state.workspaceSupported = true;
} else {
state.workspaceSupported = false;
console.log(`workspace ${workspace.name} does not contain supported files.`);
}
return state.workspaceSupported;
}

export function getOutputFolder() {
return getConfigAndReplaceVariables('codechecker.backend', 'outputFolder');
}

export function getCompilationDatabasePath() {
return getConfigAndReplaceVariables('codechecker.backend', 'compilationDatabasePath');
}
5 changes: 5 additions & 0 deletions src/utils/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class ExtensionState {
public workspaceSupported = false;
}

export const state = new ExtensionState();
Loading