Skip to content

Commit

Permalink
Fix linter errors
Browse files Browse the repository at this point in the history
  • Loading branch information
fpoli committed Sep 1, 2023
1 parent 9188f3e commit a67fb05
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 89 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,14 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>

await verificationManager.verify(
prusti!,
server.address || "",
server.address ?? "",
document.uri.fsPath,
diagnostics.VerificationTarget.StandaloneFile
);
} else {
await verificationManager.verify(
prusti!,
server.address || "",
server.address ?? "",
cratePath.path,
diagnostics.VerificationTarget.Crate
);
Expand Down
44 changes: 21 additions & 23 deletions src/toolbox/serverManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ enum State {
Unrecoverable = "Unrecoverable",
}

const stateKeys: string[] = Object.keys(State);

export interface StartOptions {
readonly cwd?: string;
readonly env?: NodeJS.ProcessEnv;
Expand All @@ -38,7 +36,7 @@ export class ServerError extends Error {

export class ServerManager {
private readonly name: string;
private readonly state: StateMachine;
private readonly state: StateMachine<State>;
private readonly log: (data: string) => void;
private readonly procExitCallback: (code: unknown) => void;
private proc?: childProcess.ChildProcessWithoutNullStreams;
Expand All @@ -50,12 +48,8 @@ export class ServerManager {
*/
public constructor(name: string, log?: (data: string) => void) {
this.name = name;
this.log = (data) => (log || console.log)(`[${this.name}] ${data}`);
this.state = new StateMachine(
`${name} state`,
State[State.Stopped],
stateKeys,
)
this.log = (data) => (log ?? console.log)(`[${this.name}] ${data}`);
this.state = new StateMachine(`${name} state`, State.Stopped);
this.procExitCallback = (code: unknown) => {
this.log(`Server process unexpected terminated with exit code ${code}`);
this.proc = undefined;
Expand Down Expand Up @@ -171,21 +165,25 @@ export class ServerManager {
this.log(`Kill server process ${this.proc?.pid}.`);
const proc = this.proc as childProcess.ChildProcessWithoutNullStreams;
proc.removeListener("exit", this.procExitCallback);
treeKill(proc.pid, "SIGKILL", (err) => {
if (err) {
this.log(`Failed to kill process tree of ${proc.pid}: ${err}`);
const succeeded = proc.kill("SIGKILL");
if (!succeeded) {
this.log(`Failed to kill process ${proc}.`);
if (proc.pid !== undefined) {
treeKill(proc.pid, "SIGKILL", (err) => {
if (err) {
this.log(`Failed to kill process tree of ${proc.pid}: ${err}`);
const succeeded = proc.kill("SIGKILL");
if (!succeeded) {
this.log(`Failed to kill process ${proc.pid}.`);
}
this.log("This is an unrecorevable error.");
this.setState(State.Unrecoverable);
} else {
// Success
this.proc = undefined;
this.setState(State.Stopped);
}
this.log("This is an unrecorevable error.");
this.setState(State.Unrecoverable);
} else {
// Success
this.proc = undefined;
this.setState(State.Stopped);
}
});
});
} else {
this.log("The process id is undefined.");
}
} else {
this.proc = undefined;
this.setState(State.Stopped);
Expand Down
73 changes: 22 additions & 51 deletions src/toolbox/stateMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,67 +10,48 @@ export class StateMachineError extends Error {

type ResolveReject = { resolve: () => void, reject: (err: Error) => void };

interface WaitingForState {
[details: string]: ResolveReject[];
}

export class StateMachine {
export class StateMachine<State extends string> {
private readonly name: string;
private readonly validStates: string[];
private currentState: string;
private waitingForState: WaitingForState = {};
private currentState: State;
private waitingForState: Map<State, ResolveReject[]> = new Map();

/**
* Construct a new state machine.
*
* @throw Will throw an error if `currentState` is not among the \
* `validStates`.
*/
public constructor(
name: string,
initialState: string,
validStates: string[],
initialState: State,
) {
this.name = name;
this.validStates = [...validStates];
for (const state of validStates) {
this.waitingForState[state] = []
}

if (!this.validStates.includes(initialState)) {
throw new StateMachineError(
this.name,
`Tried to set an invalid initial ` +
`state "${initialState}". Valid states are: ${this.validStates}`
);
}
this.currentState = initialState;
}

/**
* Return the current state.
*/
public getState(): string {
public getState(): State {
return this.currentState;
}

/**
* Set a new state.
*
* @throw Will throw an error if `newState` is not a valid state.
/*
* Get a value of `waitingForState`, inserting an empty array if the key doesn't exist.
*/
public setState(newState: string): void {
if (!this.validStates.includes(newState)) {
throw new StateMachineError(
this.name,
`Tried to set an invalid initial state "${newState}". ` +
`Valid states are: ${this.validStates}`
);
private getWaitingForState(state: State): ResolveReject[] {
let callbacks = this.waitingForState.get(state);
if (callbacks === undefined) {
callbacks = [];
this.waitingForState.set(state, callbacks);
}
return callbacks;
}

/**
* Set a new state.
*/
public setState(newState: State): void {
this.currentState = newState;
const callbacks: ResolveReject[] = this.waitingForState[newState]

const callbacks: ResolveReject[] = this.getWaitingForState(newState);

let badCallback = undefined;
while (callbacks.length) {
Expand Down Expand Up @@ -99,23 +80,13 @@ export class StateMachine {
* Return a promise that will resolve when the state becomes `targetState`.
* Only one promise - the last one - is allowed to modify the state.
* If a promise modifies the state any further promise will be rejected.
*
* @throw Will throw an error if `targetState` is not a valid state.
*/
public waitForState(targetState: string): Promise<void> {
if (!this.validStates.includes(targetState)) {
throw new StateMachineError(
this.name,
`Tried to wait for an invalid state "${targetState}". ` +
`Valid states are: ${this.validStates}`
);
}

public waitForState(targetState: State): Promise<void> {
return new Promise((resolve, reject) => {
if (this.currentState === targetState) {
resolve();
} else {
this.waitingForState[targetState].push({ resolve, reject });
this.getWaitingForState(targetState).push({ resolve, reject });
}
});
}
Expand Down
28 changes: 16 additions & 12 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,21 @@ export function spawn(
if (!status.killed) {
status.killed = true;
// TODO: Try with SIGTERM before.
treeKill(proc.pid, "SIGKILL", (err) => {
if (err) {
log(`Failed to kill process tree of ${proc.pid}: ${err}`);
const succeeded = proc.kill("SIGKILL");
if (!succeeded) {
log(`Failed to kill process ${proc}.`);
if (proc.pid !== undefined) {
treeKill(proc.pid, "SIGKILL", (err) => {
if (err) {
log(`Failed to kill process tree of ${proc.pid}: ${err}`);
const succeeded = proc.kill("SIGKILL");
if (!succeeded) {
log(`Failed to kill process ${proc.pid}.`);
}
} else {
log(`Process ${proc.pid} has been killed successfully.`);
}
} else {
log(`Process ${proc.pid} has been killed successfully.`);
}
});
});
} else {
log(`The process id is undefined.`);
}
} else {
log(`Process ${proc.pid} has already been killed.`);
}
Expand All @@ -140,15 +144,15 @@ export function spawn(
destructors.add(killProc);
}

proc.stdout.on("data", (data) => {
proc.stdout.on("data", (data: string) => {
stdout += data;
try {
onStdout?.(data);
} catch (e) {
log(`error in stdout handler for '${description}': ${e}`);
}
});
proc.stderr.on("data", (data) => {
proc.stderr.on("data", (data: string) => {
stderr += data;
try {
onStderr?.(data);
Expand Down

0 comments on commit a67fb05

Please sign in to comment.