@spyglassmc/core 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/lib/common/TwoWayMap.d.ts +21 -0
  2. package/lib/common/TwoWayMap.js +75 -0
  3. package/lib/common/index.js +5 -1
  4. package/lib/common/util.d.ts +3 -20
  5. package/lib/common/util.js +6 -40
  6. package/lib/index.js +5 -1
  7. package/lib/node/LiteralNode.d.ts +1 -1
  8. package/lib/node/LiteralNode.js +1 -1
  9. package/lib/node/ResourceLocationNode.d.ts +2 -4
  10. package/lib/node/Sequence.d.ts +2 -1
  11. package/lib/node/Sequence.js +3 -2
  12. package/lib/node/SymbolNode.d.ts +1 -1
  13. package/lib/node/SymbolNode.js +1 -1
  14. package/lib/node/index.js +5 -1
  15. package/lib/parser/float.js +1 -1
  16. package/lib/parser/index.js +5 -1
  17. package/lib/parser/integer.js +1 -1
  18. package/lib/parser/long.js +1 -1
  19. package/lib/parser/string.js +4 -2
  20. package/lib/parser/util.d.ts +25 -7
  21. package/lib/parser/util.js +50 -17
  22. package/lib/processor/checker/builtin.js +1 -1
  23. package/lib/processor/checker/index.js +5 -1
  24. package/lib/processor/colorizer/index.js +5 -1
  25. package/lib/processor/completer/builtin.js +16 -16
  26. package/lib/processor/completer/index.js +5 -1
  27. package/lib/processor/formatter/index.js +5 -1
  28. package/lib/processor/index.js +5 -1
  29. package/lib/processor/linter/builtin/undeclaredSymbol.js +3 -3
  30. package/lib/processor/linter/builtin.js +1 -1
  31. package/lib/processor/linter/index.js +5 -1
  32. package/lib/service/Config.d.ts +6 -4
  33. package/lib/service/Config.js +6 -6
  34. package/lib/service/Context.d.ts +2 -2
  35. package/lib/service/Context.js +1 -0
  36. package/lib/service/Downloader.d.ts +1 -0
  37. package/lib/service/Downloader.js +4 -0
  38. package/lib/service/ErrorReporter.js +1 -1
  39. package/lib/service/FileService.d.ts +29 -4
  40. package/lib/service/FileService.js +82 -19
  41. package/lib/service/Project.d.ts +1 -0
  42. package/lib/service/Project.js +23 -11
  43. package/lib/service/Service.d.ts +2 -2
  44. package/lib/service/Service.js +25 -15
  45. package/lib/service/fileUtil.d.ts +15 -5
  46. package/lib/service/fileUtil.js +39 -4
  47. package/lib/service/index.js +5 -1
  48. package/lib/source/LanguageError.js +1 -1
  49. package/lib/source/Source.d.ts +6 -1
  50. package/lib/source/Source.js +30 -2
  51. package/lib/source/index.js +5 -1
  52. package/lib/symbol/Symbol.d.ts +10 -10
  53. package/lib/symbol/Symbol.js +7 -6
  54. package/lib/symbol/SymbolUtil.d.ts +1 -8
  55. package/lib/symbol/SymbolUtil.js +12 -12
  56. package/lib/symbol/index.js +5 -1
  57. package/package.json +2 -2
@@ -28,8 +28,8 @@ exports.dispatch = dispatch;
28
28
  exports.fallback = exports.dispatch;
29
29
  const boolean = (node, ctx) => {
30
30
  return [
31
- Completer_1.CompletionItem.create('false', node, { kind: 21 /* Constant */ }),
32
- Completer_1.CompletionItem.create('true', node, { kind: 21 /* Constant */ }),
31
+ Completer_1.CompletionItem.create('false', node, { kind: 21 /* CompletionKind.Constant */ }),
32
+ Completer_1.CompletionItem.create('true', node, { kind: 21 /* CompletionKind.Constant */ }),
33
33
  ];
34
34
  };
35
35
  exports.boolean = boolean;
@@ -43,17 +43,17 @@ const file = (node, ctx) => {
43
43
  exports.file = file;
44
44
  const literal = node => {
45
45
  const kind = new Map([
46
- ['enum', 13 /* Enum */],
47
- ['enumMember', 20 /* EnumMember */],
48
- ['function', 3 /* Function */],
49
- ['keyword', 14 /* Keyword */],
50
- ['literal', 14 /* Keyword */],
51
- ['number', 21 /* Constant */],
52
- ['operator', 24 /* Operator */],
53
- ['property', 10 /* Property */],
54
- ['resourceLocation', 17 /* File */],
55
- ['variable', 6 /* Variable */],
56
- ]).get(node.options.colorTokenType ?? 'keyword') ?? 14 /* Keyword */;
46
+ ['enum', 13 /* CompletionKind.Enum */],
47
+ ['enumMember', 20 /* CompletionKind.EnumMember */],
48
+ ['function', 3 /* CompletionKind.Function */],
49
+ ['keyword', 14 /* CompletionKind.Keyword */],
50
+ ['literal', 14 /* CompletionKind.Keyword */],
51
+ ['number', 21 /* CompletionKind.Constant */],
52
+ ['operator', 24 /* CompletionKind.Operator */],
53
+ ['property', 10 /* CompletionKind.Property */],
54
+ ['resourceLocation', 17 /* CompletionKind.File */],
55
+ ['variable', 6 /* CompletionKind.Variable */],
56
+ ]).get(node.options.colorTokenType ?? 'keyword') ?? 14 /* CompletionKind.Keyword */;
57
57
  return node.options.pool.map(v => Completer_1.CompletionItem.create(v, node, { kind })) ?? [];
58
58
  };
59
59
  exports.literal = literal;
@@ -134,7 +134,7 @@ const resourceLocation = (node, ctx) => {
134
134
  .map(v => `${common_1.ResourceLocation.TagPrefix}${v}`)
135
135
  : [],
136
136
  ];
137
- return pool.map(v => Completer_1.CompletionItem.create(v, node, { kind: 3 /* Function */ }));
137
+ return pool.map(v => Completer_1.CompletionItem.create(v, node, { kind: 3 /* CompletionKind.Function */ }));
138
138
  };
139
139
  exports.resourceLocation = resourceLocation;
140
140
  const string = (node, ctx) => {
@@ -145,7 +145,7 @@ const string = (node, ctx) => {
145
145
  if (node.options.quotes && node.value === '') {
146
146
  return node.options.quotes.map(q => Completer_1.CompletionItem.create(`${q}${q}`, node, {
147
147
  insertText: `${q}$1${q}`,
148
- kind: 12 /* Value */,
148
+ kind: 12 /* CompletionKind.Value */,
149
149
  }));
150
150
  }
151
151
  return [];
@@ -154,7 +154,7 @@ exports.string = string;
154
154
  const symbol = (node, ctx) => {
155
155
  return Object
156
156
  .keys(ctx.symbols.query(ctx.doc, node.options.category, ...node.options.parentPath ?? []).visibleMembers)
157
- .map(v => Completer_1.CompletionItem.create(v, node, { kind: 6 /* Variable */ }));
157
+ .map(v => Completer_1.CompletionItem.create(v, node, { kind: 6 /* CompletionKind.Variable */ }));
158
158
  };
159
159
  exports.symbol = symbol;
160
160
  function registerCompleters(meta) {
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -63,11 +63,11 @@ function getAction(config, symbol, ctx) {
63
63
  function getVisibility(input) {
64
64
  switch (input) {
65
65
  case 'block':
66
- return 0 /* Block */;
66
+ return 0 /* SymbolVisibility.Block */;
67
67
  case 'file':
68
- return 1 /* File */;
68
+ return 1 /* SymbolVisibility.File */;
69
69
  case 'public':
70
- return 2 /* Public */;
70
+ return 2 /* SymbolVisibility.Public */;
71
71
  }
72
72
  }
73
73
  //# sourceMappingURL=undeclaredSymbol.js.map
@@ -108,7 +108,7 @@ function registerLinters(meta) {
108
108
  meta.registerLinter('undeclaredSymbol', {
109
109
  configValidator: configValidator.symbolLinterConfig,
110
110
  linter: undeclaredSymbol_1.undeclaredSymbol,
111
- nodePredicate: n => n.symbol && !symbol_1.NbtdocCategories.includes(n.symbol.category),
111
+ nodePredicate: n => n.symbol && !symbol_1.McdocCategories.includes(n.symbol.category),
112
112
  });
113
113
  }
114
114
  exports.registerLinters = registerLinters;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -24,15 +24,17 @@ export interface Config {
24
24
  }
25
25
  export interface EnvConfig {
26
26
  /**
27
- * Where to download data like `mcmeta` or `mc-nbtdoc` from (case-insensitive).
27
+ * Where to download data like `mcmeta` or `vanilla-mcdoc` from (case-insensitive).
28
28
  *
29
- * * `GitHub`
30
- * * `jsDelivr`: Not recommended as files from there can be outdated. Only use this if you have trouble connecting to `raw.githubusercontent.com`.
29
+ * * `GitHub`: Recommended, unless you have trouble connecting to `raw.githubusercontent.com`.
30
+ * * `fastly`
31
+ * * `jsDelivr`
32
+ * * A custom URL, with placeholder variables: `${user}`, `${repo}`, `${tag}`, and `${path}`.
31
33
  */
32
34
  dataSource: string;
33
35
  /**
34
36
  * A list of data packs the current project depends on. Each value in this array can be either an absolute file path
35
- * to a data pack folder or data pack archive (e.g. `.zip` or `.tar.gz`), or a special string like `@mc-nbtdoc`.
37
+ * to a data pack folder or data pack archive (e.g. `.zip` or `.tar.gz`), or a special string like `@vanilla-mcdoc`.
36
38
  */
37
39
  dependencies: string[];
38
40
  feature: {
@@ -21,13 +21,13 @@ var LinterSeverity;
21
21
  function toErrorSeverity(value) {
22
22
  switch (value) {
23
23
  case 'error':
24
- return 3 /* Error */;
24
+ return 3 /* ErrorSeverity.Error */;
25
25
  case 'hint':
26
- return 0 /* Hint */;
26
+ return 0 /* ErrorSeverity.Hint */;
27
27
  case 'information':
28
- return 1 /* Information */;
28
+ return 1 /* ErrorSeverity.Information */;
29
29
  case 'warning':
30
- return 2 /* Warning */;
30
+ return 2 /* ErrorSeverity.Warning */;
31
31
  }
32
32
  }
33
33
  LinterSeverity.toErrorSeverity = toErrorSeverity;
@@ -51,7 +51,7 @@ var LinterConfigValue;
51
51
  };
52
52
  }
53
53
  return {
54
- ruleSeverity: 2 /* Warning */,
54
+ ruleSeverity: 2 /* ErrorSeverity.Warning */,
55
55
  ruleValue: value,
56
56
  };
57
57
  }
@@ -118,7 +118,7 @@ exports.VanillaConfig = {
118
118
  env: {
119
119
  dataSource: 'GitHub',
120
120
  dependencies: [
121
- '@mc-nbtdoc',
121
+ '@vanilla-mcdoc',
122
122
  ],
123
123
  feature: {
124
124
  codeActions: true,
@@ -10,6 +10,7 @@ import type { RootUriString } from './fileUtil';
10
10
  import type { Logger } from './Logger';
11
11
  import type { MetaRegistry } from './MetaRegistry';
12
12
  import { Operations } from './Operations';
13
+ import type { ProfilerFactory } from './Profiler';
13
14
  import type { DocAndNode, ProjectData } from './Project';
14
15
  export interface ContextBase {
15
16
  fs: FileService;
@@ -17,6 +18,7 @@ export interface ContextBase {
17
18
  global: SymbolTable;
18
19
  logger: Logger;
19
20
  meta: MetaRegistry;
21
+ profilers: ProfilerFactory;
20
22
  project: Record<string, string>;
21
23
  roots: readonly RootUriString[];
22
24
  }
@@ -27,7 +29,6 @@ export interface ParserContext extends ContextBase {
27
29
  config: Config;
28
30
  doc: TextDocument;
29
31
  err: ErrorReporter;
30
- /** @deprecated */
31
32
  symbols: SymbolUtil;
32
33
  }
33
34
  interface ParserContextOptions {
@@ -41,7 +42,6 @@ export interface ProcessorContext extends ContextBase {
41
42
  config: Config;
42
43
  doc: TextDocument;
43
44
  src: ReadonlySource;
44
- /** @deprecated */
45
45
  symbols: SymbolUtil;
46
46
  }
47
47
  interface ProcessorContextOptions {
@@ -15,6 +15,7 @@ var ContextBase;
15
15
  global: project.symbols.global,
16
16
  logger: project.logger,
17
17
  meta: project.meta,
18
+ profilers: project.profilers,
18
19
  roots: project.roots,
19
20
  project: project.ctx,
20
21
  };
@@ -3,6 +3,7 @@ import type { Logger } from './Logger';
3
3
  declare type RemoteProtocol = 'http:' | 'https:';
4
4
  export declare type RemoteUriString = `${RemoteProtocol}${string}`;
5
5
  export declare namespace RemoteUriString {
6
+ function is(value: string): value is RemoteUriString;
6
7
  function getProtocol(uri: RemoteUriString): RemoteProtocol;
7
8
  }
8
9
  export interface DownloaderDownloadOut {
@@ -18,6 +18,10 @@ const common_1 = require("../common");
18
18
  const fileUtil_1 = require("./fileUtil");
19
19
  var RemoteUriString;
20
20
  (function (RemoteUriString) {
21
+ function is(value) {
22
+ return value.startsWith('http:') || value.startsWith('https:');
23
+ }
24
+ RemoteUriString.is = is;
21
25
  function getProtocol(uri) {
22
26
  return uri.slice(0, uri.indexOf(':') + 1);
23
27
  }
@@ -10,7 +10,7 @@ class ErrorReporter {
10
10
  /**
11
11
  * Reports a new error.
12
12
  */
13
- report(message, range, severity = 3 /* Error */, info) {
13
+ report(message, range, severity = 3 /* ErrorSeverity.Error */, info) {
14
14
  this.errors.push(source_1.LanguageError.create(message, source_1.Range.get(range), severity, info));
15
15
  }
16
16
  /**
@@ -37,12 +37,28 @@ export interface FileService extends UriProtocolSupporter {
37
37
  * Unregister the supported associated with `protocol`. Nothing happens if the `protocol` isn't supported.
38
38
  */
39
39
  unregister(protocol: Protocol): void;
40
+ /**
41
+ * Map the item at `uri` to physical disk.
42
+ *
43
+ * @returns The `file:` URI of the mapped file, or `undefined` if it cannot be mapped.
44
+ */
45
+ mapToDisk(uri: string): Promise<string | undefined>;
46
+ /**
47
+ * Map the item at `uri` from physical disk back to a (virtual) URI used by Spyglass internally.
48
+ */
49
+ mapFromDisk(uri: string): string;
40
50
  }
41
51
  export declare namespace FileService {
42
- function create(): FileService;
52
+ function create(cacheRoot: string): FileService;
43
53
  }
44
54
  export declare class FileServiceImpl implements FileService {
55
+ private readonly virtualUrisRoot?;
45
56
  private readonly supporters;
57
+ /**
58
+ * A two-way map from mapped physical URIs to virtual URIs.
59
+ */
60
+ private readonly map;
61
+ constructor(virtualUrisRoot?: `${string}/` | undefined);
46
62
  register(protocol: Protocol, supporter: UriProtocolSupporter, force?: boolean): void;
47
63
  unregister(protocol: Protocol): void;
48
64
  /**
@@ -61,6 +77,8 @@ export declare class FileServiceImpl implements FileService {
61
77
  readFile(uri: string): Promise<Buffer>;
62
78
  listFiles(): Generator<string, void, undefined>;
63
79
  listRoots(): Generator<`${string}/`, void, undefined>;
80
+ mapToDisk(virtualUri: string): Promise<string | undefined>;
81
+ mapFromDisk(mappedUri: string): string;
64
82
  }
65
83
  export declare class FileUriSupporter implements UriProtocolSupporter {
66
84
  private readonly roots;
@@ -71,12 +89,14 @@ export declare class FileUriSupporter implements UriProtocolSupporter {
71
89
  readFile(uri: string): Promise<Buffer>;
72
90
  listFiles(): Generator<string, void, undefined>;
73
91
  listRoots(): `${string}/`[];
92
+ mapToDisk(uri: string): Promise<string | undefined>;
74
93
  private static rootUriToGlob;
75
94
  static create(dependencies: readonly Dependency[], logger: Logger): Promise<FileUriSupporter>;
76
95
  }
77
- export declare class SpyglassUriSupporter implements UriProtocolSupporter {
96
+ export declare class ArchiveUriSupporter implements UriProtocolSupporter {
78
97
  private readonly entries;
79
- readonly protocol = "spyglassmc:";
98
+ readonly protocol = "archive:";
99
+ static readonly Protocol = "archive:";
80
100
  private static readonly SupportedArchiveExtnames;
81
101
  /**
82
102
  * @param entries A map from archive URIs to unzipped entries.
@@ -90,7 +110,12 @@ export declare class SpyglassUriSupporter implements UriProtocolSupporter {
90
110
  private getDataInArchive;
91
111
  listFiles(): Generator<string, void, unknown>;
92
112
  listRoots(): Generator<`${string}/`, void, unknown>;
93
- static create(dependencies: readonly Dependency[], logger: Logger, checksums: Record<RootUriString, string>): Promise<SpyglassUriSupporter>;
113
+ private static getUri;
114
+ /**
115
+ * @throws When `uri` has the wrong protocol or hostname.
116
+ */
117
+ private static decodeUri;
118
+ static create(dependencies: readonly Dependency[], logger: Logger, checksums: Record<RootUriString, string>): Promise<ArchiveUriSupporter>;
94
119
  }
95
120
  export {};
96
121
  //# sourceMappingURL=FileService.d.ts.map
@@ -2,7 +2,11 @@
2
2
  /* istanbul ignore file */
3
3
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
4
  if (k2 === undefined) k2 = k;
5
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
6
10
  }) : (function(o, m, k, k2) {
7
11
  if (k2 === undefined) k2 = k;
8
12
  o[k2] = m[k];
@@ -23,25 +27,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23
27
  return (mod && mod.__esModule) ? mod : { "default": mod };
24
28
  };
25
29
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.SpyglassUriSupporter = exports.FileUriSupporter = exports.FileServiceImpl = exports.FileService = void 0;
30
+ exports.ArchiveUriSupporter = exports.FileUriSupporter = exports.FileServiceImpl = exports.FileService = void 0;
27
31
  const crypto_1 = __importDefault(require("crypto"));
28
32
  const decompress_1 = __importDefault(require("decompress"));
29
33
  const fs_1 = __importStar(require("fs"));
30
34
  const globby_1 = __importDefault(require("globby"));
35
+ const path_1 = __importDefault(require("path"));
31
36
  const common_1 = require("../common");
37
+ const TwoWayMap_1 = require("../common/TwoWayMap");
32
38
  const fileUtil_1 = require("./fileUtil");
33
39
  const HashAlgorithm = 'sha1';
34
40
  var FileService;
35
41
  (function (FileService) {
36
- let instance;
37
- function create() {
38
- return instance ?? (instance = new FileServiceImpl());
42
+ function create(cacheRoot) {
43
+ const virtualUrisRoot = fileUtil_1.fileUtil.ensureEndingSlash(fileUtil_1.fileUtil.pathToFileUri(path_1.default.join(cacheRoot, 'virtual-uris')));
44
+ return new FileServiceImpl(virtualUrisRoot);
39
45
  }
40
46
  FileService.create = create;
41
47
  })(FileService = exports.FileService || (exports.FileService = {}));
42
48
  class FileServiceImpl {
43
- constructor() {
49
+ constructor(virtualUrisRoot) {
50
+ this.virtualUrisRoot = virtualUrisRoot;
44
51
  this.supporters = new Map();
52
+ /**
53
+ * A two-way map from mapped physical URIs to virtual URIs.
54
+ */
55
+ this.map = new TwoWayMap_1.TwoWayMap();
45
56
  }
46
57
  register(protocol, supporter, force = false) {
47
58
  if (!force && this.supporters.has(protocol)) {
@@ -88,6 +99,34 @@ class FileServiceImpl {
88
99
  yield* supporter.listRoots();
89
100
  }
90
101
  }
102
+ async mapToDisk(virtualUri) {
103
+ if (fileUtil_1.fileUtil.isFileUri(virtualUri)) {
104
+ return virtualUri;
105
+ }
106
+ if (!this.virtualUrisRoot) {
107
+ return undefined;
108
+ }
109
+ try {
110
+ let mappedUri = this.map.getKey(virtualUri);
111
+ if (mappedUri === undefined) {
112
+ mappedUri = `${this.virtualUrisRoot}${(0, common_1.getSha1)(virtualUri)}/${fileUtil_1.fileUtil.basename(virtualUri)}`;
113
+ const buffer = await this.readFile(virtualUri);
114
+ await fileUtil_1.fileUtil.writeFile(mappedUri, buffer, 0o444);
115
+ this.map.set(mappedUri, virtualUri);
116
+ }
117
+ return mappedUri;
118
+ }
119
+ catch (e) {
120
+ // Ignored.
121
+ }
122
+ return undefined;
123
+ }
124
+ mapFromDisk(mappedUri) {
125
+ if (!this.virtualUrisRoot) {
126
+ return mappedUri;
127
+ }
128
+ return this.map.get(mappedUri) ?? mappedUri;
129
+ }
91
130
  }
92
131
  exports.FileServiceImpl = FileServiceImpl;
93
132
  class FileUriSupporter {
@@ -110,6 +149,9 @@ class FileUriSupporter {
110
149
  listRoots() {
111
150
  return this.roots;
112
151
  }
152
+ async mapToDisk(uri) {
153
+ return uri;
154
+ }
113
155
  static rootUriToGlob(root) {
114
156
  return fileUtil_1.fileUtil.fileUriToPath(root) + '**/*';
115
157
  }
@@ -132,33 +174,38 @@ class FileUriSupporter {
132
174
  }
133
175
  }
134
176
  exports.FileUriSupporter = FileUriSupporter;
135
- class SpyglassUriSupporter {
177
+ // namespace ArchiveUri {
178
+ // export function is(uri: Uri): boolean {
179
+ // return uri.protocol === Protocol && uri.hostname === Hostname
180
+ // }
181
+ // }
182
+ class ArchiveUriSupporter {
136
183
  /**
137
184
  * @param entries A map from archive URIs to unzipped entries.
138
185
  */
139
186
  constructor(entries) {
140
187
  this.entries = entries;
141
- this.protocol = common_1.SpyglassUri.Protocol;
188
+ this.protocol = ArchiveUriSupporter.Protocol;
142
189
  }
143
190
  async hash(uri) {
144
- const { archiveUri, pathInArchive } = common_1.SpyglassUri.Archive.decode(new common_1.Uri(uri));
191
+ const { archiveUri, pathInArchive } = ArchiveUriSupporter.decodeUri(new common_1.Uri(uri));
145
192
  if (!pathInArchive) {
146
193
  // Hash the archive itself.
147
194
  return hashFile(archiveUri);
148
195
  }
149
196
  else {
150
197
  // Hash the corresponding file.
151
- return (0, common_1.getSha1)(await this.getDataInArchive(archiveUri, pathInArchive));
198
+ return (0, common_1.getSha1)(this.getDataInArchive(archiveUri, pathInArchive));
152
199
  }
153
200
  }
154
201
  async readFile(uri) {
155
- const { archiveUri, pathInArchive } = common_1.SpyglassUri.Archive.decode(new common_1.Uri(uri));
202
+ const { archiveUri, pathInArchive } = ArchiveUriSupporter.decodeUri(new common_1.Uri(uri));
156
203
  return this.getDataInArchive(archiveUri, pathInArchive);
157
204
  }
158
205
  /**
159
206
  * @throws
160
207
  */
161
- async getDataInArchive(archiveUri, pathInArchive) {
208
+ getDataInArchive(archiveUri, pathInArchive) {
162
209
  const entries = this.entries.get(archiveUri);
163
210
  if (!entries) {
164
211
  throw new Error(`Archive “${archiveUri}” has not been loaded into the memory`);
@@ -175,21 +222,36 @@ class SpyglassUriSupporter {
175
222
  *listFiles() {
176
223
  for (const [archiveUri, files] of this.entries.entries()) {
177
224
  for (const file of files.values()) {
178
- yield common_1.SpyglassUri.Archive.get(archiveUri, file.path);
225
+ yield ArchiveUriSupporter.getUri(archiveUri, file.path);
179
226
  }
180
227
  }
181
228
  }
182
229
  *listRoots() {
183
230
  for (const archiveUri of this.entries.keys()) {
184
- yield common_1.SpyglassUri.Archive.get(archiveUri);
231
+ yield ArchiveUriSupporter.getUri(archiveUri);
232
+ }
233
+ }
234
+ static getUri(archiveUri, pathInArchive = '') {
235
+ return `${ArchiveUriSupporter.Protocol}//${encodeURIComponent(archiveUri)}/${pathInArchive.replace(/\\/g, '/')}`;
236
+ }
237
+ /**
238
+ * @throws When `uri` has the wrong protocol or hostname.
239
+ */
240
+ static decodeUri(uri) {
241
+ if (uri.protocol !== ArchiveUriSupporter.Protocol) {
242
+ throw new Error(`Expected protocol “${ArchiveUriSupporter.Protocol}” in “${uri}”`);
185
243
  }
244
+ return {
245
+ archiveUri: decodeURIComponent(uri.hostname),
246
+ pathInArchive: uri.pathname.charAt(0) === '/' ? uri.pathname.slice(1) : uri.pathname,
247
+ };
186
248
  }
187
249
  static async create(dependencies, logger, checksums) {
188
250
  const entries = new Map();
189
251
  for (const { uri, info } of dependencies) {
190
252
  try {
191
- if (uri.startsWith('file:') && SpyglassUriSupporter.SupportedArchiveExtnames.some(ext => uri.endsWith(ext)) && (await fs_1.promises.stat(new common_1.Uri(uri))).isFile()) {
192
- const rootUri = common_1.SpyglassUri.Archive.get(uri);
253
+ if (uri.startsWith('file:') && ArchiveUriSupporter.SupportedArchiveExtnames.some(ext => uri.endsWith(ext)) && (await fs_1.promises.stat(new common_1.Uri(uri))).isFile()) {
254
+ const rootUri = ArchiveUriSupporter.getUri(uri);
193
255
  const cachedChecksum = checksums[rootUri];
194
256
  if (cachedChecksum !== undefined) {
195
257
  const checksum = await hashFile(uri);
@@ -207,11 +269,12 @@ class SpyglassUriSupporter {
207
269
  logger.error(`[SpyglassUriSupporter#create] Bad dependency “${uri}”`, e);
208
270
  }
209
271
  }
210
- return new SpyglassUriSupporter(entries);
272
+ return new ArchiveUriSupporter(entries);
211
273
  }
212
274
  }
213
- exports.SpyglassUriSupporter = SpyglassUriSupporter;
214
- SpyglassUriSupporter.SupportedArchiveExtnames = ['.tar', '.tar.bz2', '.tar.gz', '.zip'];
275
+ exports.ArchiveUriSupporter = ArchiveUriSupporter;
276
+ ArchiveUriSupporter.Protocol = 'archive:';
277
+ ArchiveUriSupporter.SupportedArchiveExtnames = ['.tar', '.tar.bz2', '.tar.gz', '.zip'];
215
278
  async function hashFile(uri) {
216
279
  return new Promise((resolve, reject) => {
217
280
  const hash = crypto_1.default.createHash(HashAlgorithm);
@@ -131,6 +131,7 @@ export declare class Project extends EventEmitter {
131
131
  close(): Promise<void>;
132
132
  restart(): Promise<void>;
133
133
  resetCache(): void;
134
+ normalizeUri(uri: string): string;
134
135
  /**
135
136
  * @returns The language ID of the file, or the file extension without the leading dot.
136
137
  */