File size: 2,603 Bytes
4e23b01
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import * as posixPath from 'node:path/posix';
import * as win32Path from 'node:path/win32';

import { Emitter } from '#/_base/event';

import type { Runtime, RuntimeCapability, RuntimePath, RuntimeStatus } from './runtime';

export class FakeRuntime implements Runtime {
  readonly capabilities: ReadonlySet<RuntimeCapability>;
  readonly environment;
  readonly path: RuntimePath;
  readonly workspace;
  readonly fs = undefined;
  readonly process = undefined;
  readonly watch = undefined;
  readonly terminal = undefined;
  private currentStatus: RuntimeStatus;
  private readonly statusEmitter = new Emitter<RuntimeStatus>();
  readonly onDidChangeStatus = this.statusEmitter.event;
  disposed = false;

  constructor(
    readonly identity: Runtime['identity'],
    options: {
      readonly status?: RuntimeStatus;
      readonly capabilities?: readonly RuntimeCapability[];
      readonly pathClass?: 'posix' | 'win32';
      readonly environment?: Partial<Runtime['environment']>;
      readonly mapWorkspaceRoots?: Runtime['workspace']['mapRoots'];
    } = {},
  ) {
    this.currentStatus = options.status ?? 'ready';
    this.capabilities = new Set(options.capabilities ?? []);
    const path = options.pathClass === 'win32' ? win32Path : posixPath;
    this.environment = {
      osKind: 'fake',
      osArch: 'fake',
      osVersion: 'fake',
      shellName: 'sh' as const,
      shellPath: '/bin/sh',
      pathClass: options.pathClass ?? 'posix',
      homeDir: options.pathClass === 'win32' ? 'C:\\Users\\fake' : '/home/fake',
      ...options.environment,
    };
    this.path = {
      separator: path.sep as '/' | '\\',
      delimiter: path.delimiter as ':' | ';',
      isAbsolute: (p) => path.isAbsolute(p),
      join: (...paths) => path.join(...paths),
      relative: (from, to) => path.relative(from, to),
      resolve: (...paths) => path.resolve(...paths),
      basename: (p) => path.basename(p),
      dirname: (p) => path.dirname(p),
    };
    this.workspace = {
      mapRoots: options.mapWorkspaceRoots ?? ((roots) => ({
        workDir: path.resolve(roots.workDir),
        additionalDirs: roots.additionalDirs?.map((root) => path.resolve(root)),
      })),
    };
  }

  get status(): RuntimeStatus {
    return this.currentStatus;
  }

  setStatus(status: RuntimeStatus): void {
    if (this.currentStatus === status) return;
    this.currentStatus = status;
    this.statusEmitter.fire(status);
  }

  dispose(): void {
    this.disposed = true;
    this.currentStatus = 'disposed';
    this.statusEmitter.fire('disposed');
    this.statusEmitter.dispose();
  }
}