Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { DatabaseItem } from "../../databases/local-databases";
import { relative } from "path";
import { CodeQLCliServer } from "../../codeql-cli/cli";
import { INITIAL_HIDE_MODELED_METHODS_VALUE } from "../shared/hide-modeled-methods";
import { getModelingStatus } from "../shared/modeling-status";
import { assertNever } from "../../common/helpers-pure";
import { ModeledMethod } from "../modeled-method";

export class MethodsUsageDataProvider
extends DisposableObject
Expand All @@ -23,6 +26,8 @@ export class MethodsUsageDataProvider
private databaseItem: DatabaseItem | undefined = undefined;
private sourceLocationPrefix: string | undefined = undefined;
private hideModeledMethods: boolean = INITIAL_HIDE_MODELED_METHODS_VALUE;
private modeledMethods: Record<string, ModeledMethod> = {};
private modifiedMethodSignatures: Set<string> = new Set();

private readonly onDidChangeTreeDataEmitter = this.push(
new EventEmitter<void>(),
Expand All @@ -47,17 +52,23 @@ export class MethodsUsageDataProvider
methods: Method[],
databaseItem: DatabaseItem,
hideModeledMethods: boolean,
modeledMethods: Record<string, ModeledMethod>,
modifiedMethodSignatures: Set<string>,
): Promise<void> {
if (
this.methods !== methods ||
this.databaseItem !== databaseItem ||
this.hideModeledMethods !== hideModeledMethods
this.hideModeledMethods !== hideModeledMethods ||
this.modeledMethods !== modeledMethods ||
this.modifiedMethodSignatures !== modifiedMethodSignatures
) {
this.methods = methods;
this.databaseItem = databaseItem;
this.sourceLocationPrefix =
await this.databaseItem.getSourceLocationPrefix(this.cliServer);
this.hideModeledMethods = hideModeledMethods;
this.modeledMethods = modeledMethods;
this.modifiedMethodSignatures = modifiedMethodSignatures;

this.onDidChangeTreeDataEmitter.fire();
}
Expand All @@ -68,7 +79,7 @@ export class MethodsUsageDataProvider
return {
label: `${item.packageName}.${item.typeName}.${item.methodName}${item.methodParameters}`,
collapsibleState: TreeItemCollapsibleState.Collapsed,
iconPath: new ThemeIcon("symbol-method"),
iconPath: this.getModelingStatusIcon(item),
};
} else {
const method = this.getParent(item);
Expand All @@ -83,11 +94,30 @@ export class MethodsUsageDataProvider
command: "codeQLModelEditor.jumpToUsageLocation",
arguments: [method, item, this.databaseItem],
},
iconPath: new ThemeIcon("error", new ThemeColor("errorForeground")),
};
}
}

private getModelingStatusIcon(method: Method): ThemeIcon {
const modeledMethod = this.modeledMethods[method.signature];
const modifiedMethod = this.modifiedMethodSignatures.has(method.signature);

const status = getModelingStatus(modeledMethod, modifiedMethod);
switch (status) {
case "unmodeled":
return new ThemeIcon("error", new ThemeColor("errorForeground"));
case "unsaved":
return new ThemeIcon("pass", new ThemeColor("testing.iconPassed"));
case "saved":
return new ThemeIcon(
"pass-filled",
new ThemeColor("testing.iconPassed"),
);
default:
assertNever(status);
}
}

private relativePathWithinDatabase(uri: string): string {
const parsedUri = Uri.parse(uri);
if (this.sourceLocationPrefix) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Method, Usage } from "../method";
import { DatabaseItem } from "../../databases/local-databases";
import { CodeQLCliServer } from "../../codeql-cli/cli";
import { ModelingStore } from "../modeling-store";
import { ModeledMethod } from "../modeled-method";

export class MethodsUsagePanel extends DisposableObject {
private readonly dataProvider: MethodsUsageDataProvider;
Expand All @@ -33,8 +34,16 @@ export class MethodsUsagePanel extends DisposableObject {
methods: Method[],
databaseItem: DatabaseItem,
hideModeledMethods: boolean,
modeledMethods: Record<string, ModeledMethod>,
modifiedMethodSignatures: Set<string>,
): Promise<void> {
await this.dataProvider.setState(methods, databaseItem, hideModeledMethods);
await this.dataProvider.setState(
methods,
databaseItem,
hideModeledMethods,
modeledMethods,
modifiedMethodSignatures,
);
const numOfApis = hideModeledMethods
? methods.filter((api) => !api.supported).length
: methods.length;
Expand Down Expand Up @@ -73,6 +82,14 @@ export class MethodsUsagePanel extends DisposableObject {
}
}),
);

this.push(
this.modelingStore.onModifiedMethodsChanged(async (event) => {
if (event.isActiveDb) {
await this.handleStateChangeEvent();
}
}),
);
}

private async handleStateChangeEvent(): Promise<void> {
Expand All @@ -82,6 +99,8 @@ export class MethodsUsagePanel extends DisposableObject {
activeState.methods,
activeState.databaseItem,
activeState.hideModeledMethods,
activeState.modeledMethods,
activeState.modifiedMethodSignatures,
);
}
}
Expand Down
26 changes: 16 additions & 10 deletions extensions/ql-vscode/src/model-editor/modeling-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export class ModelingStore extends DisposableObject {
const dbState = this.getState(dbItem);
const dbUri = dbItem.databaseUri.toString();

dbState.methods = methods;
dbState.methods = [...methods];

this.onMethodsChangedEventEmitter.fire({
methods,
Expand Down Expand Up @@ -204,13 +204,15 @@ export class ModelingStore extends DisposableObject {
methods: Record<string, ModeledMethod>,
) {
this.changeModeledMethods(dbItem, (state) => {
state.modeledMethods = methods;
state.modeledMethods = { ...methods };
});
}

public updateModeledMethod(dbItem: DatabaseItem, method: ModeledMethod) {
this.changeModeledMethods(dbItem, (state) => {
state.modeledMethods[method.signature] = method;
const newModeledMethods = { ...state.modeledMethods };
newModeledMethods[method.signature] = method;
state.modeledMethods = newModeledMethods;
});
}

Expand All @@ -219,7 +221,7 @@ export class ModelingStore extends DisposableObject {
methodSignatures: Set<string>,
) {
this.changeModifiedMethods(dbItem, (state) => {
state.modifiedMethodSignatures = methodSignatures;
state.modifiedMethodSignatures = new Set(methodSignatures);
});
}

Expand All @@ -228,9 +230,11 @@ export class ModelingStore extends DisposableObject {
methodSignatures: Iterable<string>,
) {
this.changeModifiedMethods(dbItem, (state) => {
for (const signature of methodSignatures) {
state.modifiedMethodSignatures.add(signature);
}
const newModifiedMethods = new Set([
...state.modifiedMethodSignatures,
...methodSignatures,
]);
state.modifiedMethodSignatures = newModifiedMethods;
});
}

Expand All @@ -243,9 +247,11 @@ export class ModelingStore extends DisposableObject {
methodSignatures: string[],
) {
this.changeModifiedMethods(dbItem, (state) => {
methodSignatures.forEach((signature) => {
state.modifiedMethodSignatures.delete(signature);
});
const newModifiedMethods = Array.from(
state.modifiedMethodSignatures,
).filter((s) => !methodSignatures.includes(s));

state.modifiedMethodSignatures = new Set(newModifiedMethods);
});
}

Expand Down
Loading