From 5cbb709889032fade3b729c4400374f3a43158fd Mon Sep 17 00:00:00 2001 From: SPGoding Date: Mon, 13 May 2024 23:52:59 -0500 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9B=20Use=20whatwg-url=20instead?= =?UTF-8?q?=20of=20built-in=20URLs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 109 ++++++++++++++++-- packages/core/package.json | 6 +- .../src/common/externals/NodeJsExternals.ts | 10 +- packages/core/src/common/externals/index.ts | 2 +- packages/core/src/common/util.ts | 11 ++ 5 files changed, 122 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index c18c17e5d..33a5da028 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1480,6 +1480,12 @@ "integrity": "sha512-GH8BDf8cw9AC9080uneJfulhSa7KHSMI2s/CyKePXoGNos9J486w2V4YKoeNUqIEkW4hKoEAWp6/cXTwyGj47g==", "dev": true }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "dev": true + }, "node_modules/@types/webpack": { "version": "5.28.1", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.1.tgz", @@ -1491,6 +1497,15 @@ "webpack": "^5" } }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dev": true, + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -8504,10 +8519,9 @@ "dev": true }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -11112,12 +11126,45 @@ "globby": "^11.0.4", "pako": "^2.0.4", "rfdc": "^1.3.0", - "vscode-languageserver-textdocument": "^1.0.4" + "vscode-languageserver-textdocument": "^1.0.4", + "whatwg-url": "^14.0.0" }, "devDependencies": { "@types/decompress": "^4.2.3", "@types/follow-redirects": "^1.14.1", - "@types/pako": "^2.0.0" + "@types/pako": "^2.0.0", + "@types/whatwg-url": "^11.0.4" + } + }, + "packages/core/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/core/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "packages/core/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, "packages/discord-bot": { @@ -12168,6 +12215,7 @@ "@types/decompress": "^4.2.3", "@types/follow-redirects": "^1.14.1", "@types/pako": "^2.0.0", + "@types/whatwg-url": "^11.0.4", "base64-arraybuffer": "^1.0.2", "binary-search": "^1.3.6", "chokidar": "^3.5.2", @@ -12176,7 +12224,32 @@ "globby": "^11.0.4", "pako": "^2.0.4", "rfdc": "^1.3.0", - "vscode-languageserver-textdocument": "^1.0.4" + "vscode-languageserver-textdocument": "^1.0.4", + "whatwg-url": "^14.0.0" + }, + "dependencies": { + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "requires": { + "punycode": "^2.3.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "requires": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + } + } } }, "@spyglassmc/discord-bot": { @@ -12508,6 +12581,12 @@ "integrity": "sha512-GH8BDf8cw9AC9080uneJfulhSa7KHSMI2s/CyKePXoGNos9J486w2V4YKoeNUqIEkW4hKoEAWp6/cXTwyGj47g==", "dev": true }, + "@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "dev": true + }, "@types/webpack": { "version": "5.28.1", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.1.tgz", @@ -12519,6 +12598,15 @@ "webpack": "^5" } }, + "@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dev": true, + "requires": { + "@types/webidl-conversions": "*" + } + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -17653,10 +17741,9 @@ "dev": true }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "pupa": { "version": "3.1.0", diff --git a/packages/core/package.json b/packages/core/package.json index 2764eecb1..6f7aeb102 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -22,12 +22,14 @@ "globby": "^11.0.4", "pako": "^2.0.4", "rfdc": "^1.3.0", - "vscode-languageserver-textdocument": "^1.0.4" + "vscode-languageserver-textdocument": "^1.0.4", + "whatwg-url": "^14.0.0" }, "devDependencies": { "@types/decompress": "^4.2.3", "@types/follow-redirects": "^1.14.1", - "@types/pako": "^2.0.0" + "@types/pako": "^2.0.0", + "@types/whatwg-url": "^11.0.4" }, "publishConfig": { "access": "public" diff --git a/packages/core/src/common/externals/NodeJsExternals.ts b/packages/core/src/common/externals/NodeJsExternals.ts index 73e8edfc9..373faf33b 100644 --- a/packages/core/src/common/externals/NodeJsExternals.ts +++ b/packages/core/src/common/externals/NodeJsExternals.ts @@ -142,8 +142,13 @@ Object.freeze(NodeJsExternals) * @returns A {@link fs.PathLike}. */ function toFsPathLike(path: FsLocation): fs.PathLike { + if (path instanceof Uri) { + // Convert WHATWG URL to string so that it will be converted + // to Node.js URL by the next if-block. + path = path.toString() + } if (typeof path === 'string' && path.startsWith('file:')) { - return new Uri(path) + return new url.URL(path) } return path } @@ -155,7 +160,8 @@ function toPath(path: FsLocation): string { return uriToPath(path) } -const uriToPath = (uri: string | Uri) => url.fileURLToPath(uri) +const uriToPath = (uri: string | Uri) => + url.fileURLToPath(uri instanceof Uri ? new url.URL(uri.toString()) : uri) const uriFromPath = (path: string) => url.pathToFileURL(path).toString() class ChokidarWatcherWrapper extends EventEmitter implements FsWatcher { diff --git a/packages/core/src/common/externals/index.ts b/packages/core/src/common/externals/index.ts index 73c51e97c..866fcd444 100644 --- a/packages/core/src/common/externals/index.ts +++ b/packages/core/src/common/externals/index.ts @@ -84,7 +84,7 @@ export interface ExternalFileSystem { } /** - * A file file URI string or a URI object. + * A file URI string or a URI object. */ export type FsLocation = string | Uri diff --git a/packages/core/src/common/util.ts b/packages/core/src/common/util.ts index 9e2b5977a..bbf707784 100644 --- a/packages/core/src/common/util.ts +++ b/packages/core/src/common/util.ts @@ -1,10 +1,21 @@ import externalBinarySearch from 'binary-search' import rfdc from 'rfdc' +import { URL } from 'whatwg-url' import type { AstNode } from '../node/index.js' import type { ProcessorContext } from '../service/index.js' import type { Externals } from './externals/index.js' import type { DeepReadonly } from './ReadonlyProxy.js' +// Spyglass uses the URL class provided by the +// [spec](https://url.spec.whatwg.org/)-compliant `whatwg-url` package instead +// of the broken one shipped with browsers that do not parse non-special scheme +// URLs with hosts properly. +// +// * [Chromium bug](https://issues.chromium.org/issues/40587286) +// * [FireFox bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1374505) +// +// We use the name "URI" instead of "URL" when possible, since it is what +// LSP has chosen to use for the string that uniquely identifies a file. export const Uri = URL export type Uri = URL From 443b71842a36db06a21b2ec020745f415b3d82bf Mon Sep 17 00:00:00 2001 From: SPGoding Date: Mon, 13 May 2024 23:53:36 -0500 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20Update=20extension=20depende?= =?UTF-8?q?ncy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/vscode-extension/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index d90feb9ff..851645a53 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -44,7 +44,7 @@ } }, "extensionDependencies": [ - "arcensoth.language-mcfunction" + "MinecraftCommands.syntax-mcfunction" ], "devDependencies": { "@types/vscode": "1.67.0", From fa3db917577e6bc66773ef51d27b02dfb498e05b Mon Sep 17 00:00:00 2001 From: SPGoding Date: Mon, 13 May 2024 23:55:34 -0500 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9B=20Keep=20readonly=20status=20f?= =?UTF-8?q?or=20virtual=20URI=20mapped=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/service/FileService.ts | 79 ++++++++++++------------ packages/core/src/service/fileUtil.ts | 7 +++ 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/packages/core/src/service/FileService.ts b/packages/core/src/service/FileService.ts index aeed67e0a..3515c597b 100644 --- a/packages/core/src/service/FileService.ts +++ b/packages/core/src/service/FileService.ts @@ -161,6 +161,18 @@ export class FileServiceImpl implements FileService { virtualUri, ) }` + + // Delete old mapped file if it exists. This makes sure the + // readonly permission on the file is not removed by it being + // overwritten. + try { + await fileUtil.unlink(this.externals, mappedUri) + } catch (e) { + if (!this.externals.error.isKind(e, 'ENOENT')) { + throw e + } + } + const buffer = await this.readFile(virtualUri) await fileUtil.writeFile(this.externals, mappedUri, buffer, 0o444) this.map.set(mappedUri, virtualUri) @@ -258,7 +270,7 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { readonly protocol = ArchiveUriSupporter.Protocol /** - * @param entries A map from archive URIs to unzipped entries. + * @param entries A map from archive names to unzipped entries. */ private constructor( private readonly externals: Externals, @@ -266,83 +278,81 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { ) {} async hash(uri: string): Promise { - const { archiveUri, pathInArchive } = ArchiveUriSupporter.decodeUri( + const { archiveName, pathInArchive } = ArchiveUriSupporter.decodeUri( new Uri(uri), ) if (!pathInArchive) { // Hash the archive itself. - return hashFile(this.externals, archiveUri) + return hashFile(this.externals, archiveName) } else { // Hash the corresponding file. return this.externals.crypto.getSha1( - this.getDataInArchive(archiveUri, pathInArchive), + this.getDataInArchive(archiveName, pathInArchive), ) } } async readFile(uri: string): Promise { - const { archiveUri, pathInArchive } = ArchiveUriSupporter.decodeUri( + const { archiveName, pathInArchive } = ArchiveUriSupporter.decodeUri( new Uri(uri), ) - return this.getDataInArchive(archiveUri, pathInArchive) + return this.getDataInArchive(archiveName, pathInArchive) } /** * @throws */ private getDataInArchive( - archiveUri: string, + archiveName: string, pathInArchive: string, ): Uint8Array { - const entries = this.entries.get(archiveUri) + const entries = this.entries.get(archiveName) if (!entries) { throw new Error( - `Archive “${archiveUri}” has not been loaded into the memory`, + `Archive “${archiveName}” has not been loaded into the memory`, ) } const entry = entries.get(pathInArchive) if (!entry) { throw new Error( - `Path “${pathInArchive}” does not exist in archive “${archiveUri}”`, + `Path “${pathInArchive}” does not exist in archive “${archiveName}”`, ) } if (entry.type !== 'file') { throw new Error( - `Path “${pathInArchive}” in archive “${archiveUri}” is not a file`, + `Path “${pathInArchive}” in archive “${archiveName}” is not a file`, ) } return entry.data } *listFiles() { - for (const [archiveUri, files] of this.entries.entries()) { + for (const [archiveName, files] of this.entries.entries()) { for (const file of files.values()) { - yield ArchiveUriSupporter.getUri(archiveUri, file.path) + yield ArchiveUriSupporter.getUri(archiveName, file.path) } } } *listRoots() { - for (const archiveUri of this.entries.keys()) { - yield ArchiveUriSupporter.getUri(archiveUri) + for (const archiveName of this.entries.keys()) { + yield ArchiveUriSupporter.getUri(archiveName) } } - private static getUri(archiveUri: string): RootUriString - private static getUri(archiveUri: string, pathInArchive: string): string - private static getUri(archiveUri: string, pathInArchive = '') { - return `${ArchiveUriSupporter.Protocol}${ - encodeURIComponent( - archiveUri, - ) - }?path=${encodeURIComponent(pathInArchive.replace(/\\/g, '/'))}` + private static getUri(archiveName: string): RootUriString + private static getUri(archiveName: string, pathInArchive: string): string + private static getUri(archiveName: string, pathInArchive = '') { + return `${ArchiveUriSupporter.Protocol}//${archiveName}/${ + pathInArchive.replace(/\\/g, '/') + }` } /** * @throws When `uri` has the wrong protocol or hostname. */ private static decodeUri(uri: Uri): { - archiveUri: string + archiveName: string pathInArchive: string } { if (uri.protocol !== ArchiveUriSupporter.Protocol) { @@ -350,12 +360,12 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { `Expected protocol “${ArchiveUriSupporter.Protocol}” in “${uri}”`, ) } - const path = uri.searchParams.get('path') + const path = uri.pathname if (!path) { throw new Error(`Missing path in archive uri “${uri.toString()}”`) } return { - archiveUri: decodeURIComponent(uri.pathname), + archiveName: uri.host, pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path, } } @@ -364,7 +374,6 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { dependencies: readonly Dependency[], externals: Externals, logger: Logger, - checksums: Record, ): Promise { const entries = new Map>() @@ -377,17 +386,9 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { ) && (await externals.fs.stat(uri)).isFile() ) { - const rootUri = ArchiveUriSupporter.getUri(uri) - const cachedChecksum: string | undefined = checksums[rootUri] - if (cachedChecksum !== undefined) { - const checksum = await hashFile(externals, uri) - if (cachedChecksum === checksum) { - // The dependency has not changed since last cache. - logger.info( - `[SpyglassUriSupporter#create] Skipped decompressing “${uri}” thanks to cache ${checksum}`, - ) - continue - } + const archiveName = fileUtil.basename(uri) + if (entries.has(archiveName)) { + throw new Error(`A different URI with ${archiveName} already exists`) } const files = await externals.archive.decompressBall( @@ -399,7 +400,7 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { }, ) entries.set( - uri, + archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])), ) } diff --git a/packages/core/src/service/fileUtil.ts b/packages/core/src/service/fileUtil.ts index 970568011..9faefeeb4 100644 --- a/packages/core/src/service/fileUtil.ts +++ b/packages/core/src/service/fileUtil.ts @@ -155,6 +155,13 @@ export namespace fileUtil { return chmod(externals, path, 0o444) } + export async function unlink( + externals: Externals, + path: FsLocation, + ): Promise { + return externals.fs.unlink(path) + } + export async function readFile( externals: Externals, path: FsLocation, From f72c6db11c9ebb7fea06683d76e59bb9179ab4fc Mon Sep 17 00:00:00 2001 From: SPGoding Date: Mon, 13 May 2024 23:56:29 -0500 Subject: [PATCH 4/4] =?UTF-8?q?=E2=9C=A8=20Add=20@vanilla-datapack=20depen?= =?UTF-8?q?dency=20provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/service/Config.ts | 5 +++- packages/core/src/service/FileService.ts | 4 ++- packages/core/src/service/Project.ts | 1 - packages/java-edition/src/dependency/index.ts | 27 +++++++++++++++++++ packages/java-edition/src/index.ts | 6 +++++ packages/language-server/src/server.ts | 5 ++++ 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/core/src/service/Config.ts b/packages/core/src/service/Config.ts index 74e6a021b..568b64b2c 100644 --- a/packages/core/src/service/Config.ts +++ b/packages/core/src/service/Config.ts @@ -321,7 +321,10 @@ export namespace SymbolLinterConfig { export const VanillaConfig: Config = { env: { dataSource: 'GitHub', - dependencies: ['@vanilla-mcdoc'], + dependencies: [ + '@vanilla-datapack', + '@vanilla-mcdoc', + ], feature: { codeActions: true, colors: true, diff --git a/packages/core/src/service/FileService.ts b/packages/core/src/service/FileService.ts index 3515c597b..d361200ea 100644 --- a/packages/core/src/service/FileService.ts +++ b/packages/core/src/service/FileService.ts @@ -388,7 +388,9 @@ export class ArchiveUriSupporter implements UriProtocolSupporter { ) { const archiveName = fileUtil.basename(uri) if (entries.has(archiveName)) { - throw new Error(`A different URI with ${archiveName} already exists`) + throw new Error( + `A different URI with ${archiveName} already exists`, + ) } const files = await externals.archive.decompressBall( diff --git a/packages/core/src/service/Project.ts b/packages/core/src/service/Project.ts index ad95c3676..f77e5ea80 100644 --- a/packages/core/src/service/Project.ts +++ b/packages/core/src/service/Project.ts @@ -512,7 +512,6 @@ export class Project implements ExternalEventEmitter { dependencies, this.externals, this.logger, - this.cacheService.checksums.roots, ) this.fs.register('file:', fileUriSupporter, true) this.fs.register( diff --git a/packages/java-edition/src/dependency/index.ts b/packages/java-edition/src/dependency/index.ts index 560a47236..c0b103152 100644 --- a/packages/java-edition/src/dependency/index.ts +++ b/packages/java-edition/src/dependency/index.ts @@ -231,6 +231,33 @@ async function downloadGitHubRepo({ } /* istanbul ignore next */ +/** + * @throws Network/file system errors. + * + * @returns + * - `startDepth`: The amount of level to skip when unzipping the tarball. + * - `uri`: URI to the `.tar.gz` file. + */ +export async function getVanillaDatapack( + downloader: core.Downloader, + version: string, + isLatest: boolean, +): Promise { + const uri = await downloadGitHubRepo({ + defaultBranch: 'data', + downloader, + getTag: (v) => `${v}-data`, + owner: 'misode', + repo: 'mcmeta', + isLatest, + version, + }) + return { + info: { startDepth: 1 }, + uri, + } +} + /** * @throws Network/file system errors. * diff --git a/packages/java-edition/src/index.ts b/packages/java-edition/src/index.ts index a3192784d..8395e9ad2 100644 --- a/packages/java-edition/src/index.ts +++ b/packages/java-edition/src/index.ts @@ -3,6 +3,7 @@ import * as mcdoc from '@spyglassmc/mcdoc' import * as nbt from '@spyglassmc/nbt' import { uriBinder } from './binder/index.js' import type { McmetaSummary } from './dependency/index.js' +import { getVanillaDatapack } from './dependency/index.js' import { getMcmetaSummary, getVanillaMcdoc, @@ -60,6 +61,11 @@ export const initialize: core.ProjectInitializer = async (ctx) => { versions, }) + meta.registerDependencyProvider( + '@vanilla-datapack', + () => getVanillaDatapack(downloader, version, isLatest), + ) + meta.registerDependencyProvider( '@vanilla-mcdoc', () => getVanillaMcdoc(downloader), diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 8a8c0562a..13d66186c 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -113,6 +113,11 @@ connection.onInitialize(async (params) => { }) service.project .on('documentErrored', ({ errors, uri, version }) => { + if (!core.fileUtil.isFileUri(uri)) { + // Don't send errors for non-file URIs to the client. + return + } + connection.sendDiagnostics({ diagnostics: toLS.diagnostics(errors), uri: uri,