From 8d2f6b9634fd3a8d81ba72a3af30ea518932a48e Mon Sep 17 00:00:00 2001 From: Georgii Plotnikov Date: Wed, 18 Feb 2026 16:08:51 +0900 Subject: [PATCH 1/2] Update VSCode extension after removing LLVM --- editors/vscode/QA_GUIDE.md | 6 +- editors/vscode/src/test/doctor-format.test.ts | 4 +- editors/vscode/src/test/doctor.test.ts | 15 +- .../vscode/src/test/e2e-installation.test.ts | 157 +++--------------- 4 files changed, 39 insertions(+), 143 deletions(-) diff --git a/editors/vscode/QA_GUIDE.md b/editors/vscode/QA_GUIDE.md index f5e88f26..20a7f7e4 100644 --- a/editors/vscode/QA_GUIDE.md +++ b/editors/vscode/QA_GUIDE.md @@ -1,8 +1,8 @@ # Inference VS Code Extension -- Manual QA Guide **Version:** 0.0.3 -**Branch:** `116-integrate-infs-to-vscode-extension` -**Date:** 2026-02-02 +**Branch:** `127-update-vscode-extension-after-removing-llvm` +**Date:** 2026-02-18 --- @@ -46,7 +46,7 @@ Many QA cases below are covered by automated tests (`npm test`). Cases marked wi | 0.1 | `npm install` in `editors/vscode/` | Installs without errors | | 0.2 | `npm run build` | Builds `dist/extension.js` without errors | | 0.3 | `npm run build:prod` | Production build succeeds | -| 0.4 | `npm test` | All 220 tests pass, 0 failures | +| 0.4 | `npm test` | All 216 tests pass, 0 failures | | 0.5 | `npm run package` | Produces `inference-0.0.3.vsix` without errors | --- diff --git a/editors/vscode/src/test/doctor-format.test.ts b/editors/vscode/src/test/doctor-format.test.ts index 3b513ee0..df8142ea 100644 --- a/editors/vscode/src/test/doctor-format.test.ts +++ b/editors/vscode/src/test/doctor-format.test.ts @@ -23,7 +23,7 @@ describe('formatDoctorChecks (QA Section 4.2)', () => { const result = makeDoctorResult({ checks: [ { name: 'infs binary', status: 'ok', message: 'Found at /usr/bin/infs' }, - { name: 'libLLVM', status: 'warn', message: 'Not found' }, + { name: 'infc', status: 'warn', message: 'Not found' }, { name: 'Default toolchain', status: 'fail', message: 'Not installed' }, ], summary: 'Some checks failed.', @@ -32,7 +32,7 @@ describe('formatDoctorChecks (QA Section 4.2)', () => { const lines = formatDoctorChecks(result); assert.ok(lines.some((l) => l.includes('[OK]') && l.includes('infs binary'))); - assert.ok(lines.some((l) => l.includes('[WARN]') && l.includes('libLLVM'))); + assert.ok(lines.some((l) => l.includes('[WARN]') && l.includes('infc'))); assert.ok(lines.some((l) => l.includes('[FAIL]') && l.includes('Default toolchain'))); }); diff --git a/editors/vscode/src/test/doctor.test.ts b/editors/vscode/src/test/doctor.test.ts index ee3714a2..06ad07d4 100644 --- a/editors/vscode/src/test/doctor.test.ts +++ b/editors/vscode/src/test/doctor.test.ts @@ -12,15 +12,14 @@ describe('parseDoctorOutput', () => { ' [OK] Platform: Detected linux-x64', ' [OK] Toolchain directory: Found at /home/user/.inference', ' [OK] Default toolchain: Set to 0.1.0', - ' [OK] inf-llc: Found inf-llc in PATH', - ' [OK] rust-lld: Found rust-lld in PATH', + ' [OK] infc: Found infc in PATH', '', 'All checks passed. The toolchain is ready to use.', ].join('\n'); const result = parseDoctorOutput(stdout); - assert.strictEqual(result.checks.length, 6); + assert.strictEqual(result.checks.length, 5); assert.strictEqual(result.hasErrors, false); assert.strictEqual(result.hasWarnings, false); assert.strictEqual( @@ -45,7 +44,7 @@ describe('parseDoctorOutput', () => { '', ' [OK] infs binary: Found at /home/user/.inference/bin/infs', ' [OK] Platform: Detected linux-x64', - ' [WARN] libLLVM: Not found in /path. Some features may not work.', + ' [WARN] Default toolchain: No default toolchain set.', '', 'Some warnings were found. The toolchain may work but could have issues.', ].join('\n'); @@ -56,7 +55,7 @@ describe('parseDoctorOutput', () => { assert.strictEqual(result.hasErrors, false); assert.strictEqual(result.hasWarnings, true); assert.strictEqual(result.checks[2].status, 'warn'); - assert.strictEqual(result.checks[2].name, 'libLLVM'); + assert.strictEqual(result.checks[2].name, 'Default toolchain'); assert.strictEqual( result.summary, 'Some warnings were found. The toolchain may work but could have issues.', @@ -90,7 +89,7 @@ describe('parseDoctorOutput', () => { '', ' [OK] infs binary: Found at /usr/local/bin/infs', ' [WARN] Default toolchain: No default toolchain set.', - ' [FAIL] inf-llc: Not found.', + ' [FAIL] infc: Not found.', '', "Some checks failed. Run 'infs install' to install the toolchain.", ].join('\n'); @@ -155,7 +154,7 @@ describe('parseDoctorOutput', () => { 'Checking Inference toolchain installation...', '', ' [OK] infs binary: Found at /usr/local/bin/infs', - ' [WARN] libLLVM: Not found', + ' [WARN] Default toolchain: No default set', '', 'Some warnings found.', ].join('\r\n'); @@ -173,7 +172,7 @@ describe('parseDoctorOutput', () => { it('handles mixed LF and CRLF', () => { const stdout = ' [OK] Platform: Detected linux-x64\r\n' + - ' [FAIL] inf-llc: Not found\n' + + ' [FAIL] infc: Not found\n' + 'Checks failed.\n'; const result = parseDoctorOutput(stdout); diff --git a/editors/vscode/src/test/e2e-installation.test.ts b/editors/vscode/src/test/e2e-installation.test.ts index 98c57ff4..43e05425 100644 --- a/editors/vscode/src/test/e2e-installation.test.ts +++ b/editors/vscode/src/test/e2e-installation.test.ts @@ -11,8 +11,6 @@ import { extractArchive } from '../utils/extract'; import { exec } from '../utils/exec'; import { parseDoctorOutput } from '../toolchain/doctor'; import { findLatestRelease, type ReleaseEntry } from '../toolchain/manifest'; -import { detectPlatform } from '../toolchain/platform'; - /** * End-to-end installation tests. * @@ -26,8 +24,6 @@ import { detectPlatform } from '../toolchain/platform'; * works without needing the `vscode` module. */ -const platform = detectPlatform(); - // These e2e tests require a Unix platform (shell scripts as fake binaries). const isUnix = process.platform !== 'win32'; @@ -99,11 +95,8 @@ case "\$1" in echo "\${VERSION}" > "\${INFERENCE_HOME}/default" mkdir -p "\${INFERENCE_HOME}/bin" - for bin in infc inf-llc rust-lld; do - SOURCE="\${TOOLCHAIN_DIR}/bin/\${bin}" - if [ ! -f "\${SOURCE}" ]; then - SOURCE="\${TOOLCHAIN_DIR}/\${bin}" - fi + for bin in infc; do + SOURCE="\${TOOLCHAIN_DIR}/\${bin}" if [ -f "\${SOURCE}" ]; then ln -sf "\${SOURCE}" "\${INFERENCE_HOME}/bin/\${bin}" fi @@ -149,46 +142,18 @@ case "\$1" in HAS_WARN=1 fi - # Check inf-llc + # Check infc DEFAULT_VERSION=\$(cat "\${INFERENCE_HOME}/default" 2>/dev/null || echo "") if [ -n "\${DEFAULT_VERSION}" ]; then - INF_LLC="\${INFERENCE_HOME}/toolchains/\${DEFAULT_VERSION}/bin/inf-llc" - if [ -f "\${INF_LLC}" ]; then - echo " [OK] inf-llc: Found at \${INF_LLC}" - else - echo " [FAIL] inf-llc: Not found" - HAS_FAIL=1 - fi - fi - - # Check rust-lld - if [ -n "\${DEFAULT_VERSION}" ]; then - RUST_LLD="\${INFERENCE_HOME}/toolchains/\${DEFAULT_VERSION}/bin/rust-lld" - if [ -f "\${RUST_LLD}" ]; then - echo " [OK] rust-lld: Found at \${RUST_LLD}" + INFC="\${INFERENCE_HOME}/toolchains/\${DEFAULT_VERSION}/infc" + if [ -f "\${INFC}" ]; then + echo " [OK] infc: Found at \${INFC}" else - echo " [FAIL] rust-lld: Not found" + echo " [FAIL] infc: Not found" HAS_FAIL=1 fi fi - # Check libLLVM (Linux only) - if [ -n "\${DEFAULT_VERSION}" ]; then - LIB_DIR="\${INFERENCE_HOME}/toolchains/\${DEFAULT_VERSION}/lib" - if [ -d "\${LIB_DIR}" ]; then - FOUND_LIB=\$(ls "\${LIB_DIR}"/libLLVM*.so* 2>/dev/null | head -1) - if [ -n "\${FOUND_LIB}" ]; then - echo " [OK] libLLVM: Found \${FOUND_LIB}" - else - echo " [WARN] libLLVM: Not found in \${LIB_DIR}" - HAS_WARN=1 - fi - else - echo " [WARN] libLLVM: Library directory not found at \${LIB_DIR}" - HAS_WARN=1 - fi - fi - echo "" if [ "\${HAS_FAIL}" = "1" ]; then echo "Some checks failed. Run 'infs install' to install the toolchain." @@ -215,31 +180,14 @@ esac * * Structure mirrors the real GitHub release: * ./infc - * ./bin/inf-llc - * ./bin/rust-lld - * ./lib/libLLVM.so.21.1-rust-1.94.0-nightly */ -function buildFakeInfcArchive(archivePath: string, opts?: { skipLib?: boolean }): void { +function buildFakeInfcArchive(archivePath: string): void { const sourceDir = archivePath + '-source'; - fs.mkdirSync(path.join(sourceDir, 'bin'), { recursive: true }); + fs.mkdirSync(sourceDir, { recursive: true }); fs.writeFileSync(path.join(sourceDir, 'infc'), '#!/bin/sh\necho "infc 0.0.1-test"\n'); fs.chmodSync(path.join(sourceDir, 'infc'), 0o755); - fs.writeFileSync(path.join(sourceDir, 'bin', 'inf-llc'), '#!/bin/sh\necho "inf-llc"\n'); - fs.chmodSync(path.join(sourceDir, 'bin', 'inf-llc'), 0o755); - - fs.writeFileSync(path.join(sourceDir, 'bin', 'rust-lld'), '#!/bin/sh\necho "rust-lld"\n'); - fs.chmodSync(path.join(sourceDir, 'bin', 'rust-lld'), 0o755); - - if (!opts?.skipLib) { - fs.mkdirSync(path.join(sourceDir, 'lib'), { recursive: true }); - fs.writeFileSync( - path.join(sourceDir, 'lib', 'libLLVM.so.21.1-rust-1.94.0-nightly'), - 'fake-llvm-lib', - ); - } - execSync(`tar -czf "${archivePath}" -C "${sourceDir}" .`); fs.rmSync(sourceDir, { recursive: true }); } @@ -448,56 +396,33 @@ describe('e2e installation', { skip: !isUnix ? 'Unix-only tests' : undefined }, const toolchainDir = path.join(home, 'toolchains', '0.0.1-test'); assert.ok(fs.existsSync(toolchainDir), 'toolchain dir should exist'); assert.ok(fs.existsSync(path.join(toolchainDir, 'infc')), 'infc should exist'); - assert.ok(fs.existsSync(path.join(toolchainDir, 'bin', 'inf-llc')), 'inf-llc should exist'); - assert.ok(fs.existsSync(path.join(toolchainDir, 'bin', 'rust-lld')), 'rust-lld should exist'); - }); - - it('creates the lib directory with libLLVM', () => { - const libDir = path.join(home, 'toolchains', '0.0.1-test', 'lib'); - assert.ok(fs.existsSync(libDir), 'lib/ directory should exist'); - const files = fs.readdirSync(libDir); - const hasLlvm = files.some( - (f) => f.startsWith('libLLVM') && f.includes('.so'), - ); - assert.ok(hasLlvm, `Expected libLLVM*.so in ${libDir}, found: ${files}`); }); it('creates symlinks in bin directory', () => { const binDir = path.join(home, 'bin'); assert.ok(fs.existsSync(path.join(binDir, 'infc')), 'infc symlink should exist'); - assert.ok(fs.existsSync(path.join(binDir, 'inf-llc')), 'inf-llc symlink should exist'); - assert.ok(fs.existsSync(path.join(binDir, 'rust-lld')), 'rust-lld symlink should exist'); }); }); - describe('missing lib directory triggers doctor warning', () => { + describe('missing infc triggers doctor failure', () => { let parsed: ReturnType; - let doctorWarnings: boolean; + let doctorFailed: boolean; before(async () => { - const home = path.join(tmpDir, 'nolib-home'); + const home = path.join(tmpDir, 'noinfc-home'); const binDir = path.join(home, 'bin'); - const version = '0.0.1-nolib'; + const version = '0.0.1-noinfc'; const toolchainDir = path.join(home, 'toolchains', version); - // Manually create toolchain structure WITHOUT lib/ - fs.mkdirSync(path.join(toolchainDir, 'bin'), { recursive: true }); + fs.mkdirSync(toolchainDir, { recursive: true }); fs.mkdirSync(binDir, { recursive: true }); - fs.writeFileSync(path.join(toolchainDir, 'infc'), '#!/bin/sh\necho infc\n'); - fs.chmodSync(path.join(toolchainDir, 'infc'), 0o755); - fs.writeFileSync(path.join(toolchainDir, 'bin', 'inf-llc'), '#!/bin/sh\necho inf-llc\n'); - fs.chmodSync(path.join(toolchainDir, 'bin', 'inf-llc'), 0o755); - fs.writeFileSync(path.join(toolchainDir, 'bin', 'rust-lld'), '#!/bin/sh\necho rust-lld\n'); - fs.chmodSync(path.join(toolchainDir, 'bin', 'rust-lld'), 0o755); - fs.writeFileSync(path.join(home, 'default'), version); - // Copy infs binary from a previously downloaded archive const manifest = await fetchJson(`${baseUrl}/releases.json`); const match = findLatestRelease(manifest, { id: 'linux-x64' }); assert.ok(match); - const archiveTmp = fs.mkdtempSync(path.join(os.tmpdir(), 'infs-nolib-')); + const archiveTmp = fs.mkdtempSync(path.join(os.tmpdir(), 'infs-noinfc-')); const archivePath = path.join(archiveTmp, 'infs.tar.gz'); try { await downloadFile(match.fileUrl, { destPath: archivePath }); @@ -506,16 +431,6 @@ describe('e2e installation', { skip: !isUnix ? 'Unix-only tests' : undefined }, fs.rmSync(archiveTmp, { recursive: true, force: true }); } - // Create symlinks - for (const bin of ['infc', 'inf-llc', 'rust-lld']) { - const source = bin === 'infc' - ? path.join(toolchainDir, bin) - : path.join(toolchainDir, 'bin', bin); - const target = path.join(binDir, bin); - try { fs.unlinkSync(target); } catch { /* ignore */ } - fs.symlinkSync(source, target); - } - const infsPath = path.join(binDir, 'infs'); const sep = ':'; const augmentedPath = `${binDir}${sep}${process.env['PATH'] ?? ''}`; @@ -526,26 +441,26 @@ describe('e2e installation', { skip: !isUnix ? 'Unix-only tests' : undefined }, }); parsed = parseDoctorOutput(doctorResult.stdout); - doctorWarnings = doctorResult.exitCode !== 0 || parsed.hasErrors || parsed.hasWarnings; + doctorFailed = doctorResult.exitCode !== 0 || parsed.hasErrors; }); - it('reports doctor warnings', () => { - assert.strictEqual(doctorWarnings, true); + it('reports doctor failure', () => { + assert.strictEqual(doctorFailed, true); }); - it('libLLVM check reports warning', () => { - const libCheck = parsed.checks.find( - (c) => c.name === 'libLLVM', + it('infc check reports failure', () => { + const infcCheck = parsed.checks.find( + (c) => c.name === 'infc', ); - assert.ok(libCheck, 'Should have a libLLVM check'); - assert.strictEqual(libCheck.status, 'warn'); + assert.ok(infcCheck, 'Should have an infc check'); + assert.strictEqual(infcCheck.status, 'fail'); }); - it('non-lib checks still pass', () => { - const nonLibChecks = parsed.checks.filter( - (c) => c.name !== 'libLLVM', + it('non-infc checks still pass', () => { + const otherChecks = parsed.checks.filter( + (c) => c.name !== 'infc', ); - for (const check of nonLibChecks) { + for (const check of otherChecks) { assert.strictEqual( check.status, 'ok', @@ -756,24 +671,6 @@ describe('e2e installation', { skip: !isUnix ? 'Unix-only tests' : undefined }, assert.ok(fs.existsSync(path.join(extractDir, 'infc'))); }); - it('has inf-llc inside bin/', () => { - assert.ok(fs.existsSync(path.join(extractDir, 'bin', 'inf-llc'))); - }); - - it('has rust-lld inside bin/', () => { - assert.ok(fs.existsSync(path.join(extractDir, 'bin', 'rust-lld'))); - }); - - it('has lib/ directory with libLLVM', () => { - const libDir = path.join(extractDir, 'lib'); - assert.ok(fs.existsSync(libDir)); - const files = fs.readdirSync(libDir); - assert.ok( - files.some((f) => f.startsWith('libLLVM') && f.includes('.so')), - `Expected libLLVM*.so in lib/, found: ${files}`, - ); - }); - it('binaries have executable permissions', () => { const infcStat = fs.statSync(path.join(extractDir, 'infc')); assert.ok( From 80a123c034d8facef9b292fc6872b502bdd34dc5 Mon Sep 17 00:00:00 2001 From: Georgii Plotnikov Date: Thu, 19 Feb 2026 07:36:47 +0900 Subject: [PATCH 2/2] Update VS Code extension tests and QA documentation after LLVM removal --- CHANGELOG.md | 7 +++++++ book/appendix/llvm-features.md | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0326bd47..41e97805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -132,6 +132,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add Getting Started walkthrough to VS Code extension ([#116]) - Four-step guided setup: install toolchain, verify with doctor, create project, build - Add status bar integration showing toolchain health at a glance ([#116]) +- Update VS Code extension tests and QA docs after LLVM removal ([#127]) + - Remove `inf-llc`, `rust-lld`, `libLLVM` references from e2e tests and doctor tests + - Update fake `infs` shell script to use flat toolchain layout (`TOOLCHAIN_DIR/infc`, no `bin/` subdirectory) + - Simplify `buildFakeInfcArchive()` to emit only `infc` binary + - Update doctor check expectations from 6 to 5 checks (single `infc` check replaces `inf-llc`, `rust-lld`, `libLLVM`) + - Change "missing lib directory triggers doctor warning" to "missing infc triggers doctor failure" ### Language @@ -281,3 +287,4 @@ Initial tagged release. [#116]: https://github.com/Inferara/inference/pull/116 [#125]: https://github.com/Inferara/inference/pull/125 [#126]: https://github.com/Inferara/inference/pull/126 +[#127]: https://github.com/Inferara/inference/pull/127 diff --git a/book/appendix/llvm-features.md b/book/appendix/llvm-features.md index 1c97e8f5..6c586d51 100644 --- a/book/appendix/llvm-features.md +++ b/book/appendix/llvm-features.md @@ -1,4 +1,6 @@ -# Appendix B: LLVM Features +# Appendix B: LLVM Features (Legacy) + +> **Note:** Starting from the version after v0.0.1-beta.3, the Inference compiler no longer uses LLVM. WebAssembly is generated directly via `wasm-encoder`. This appendix is preserved as a reference for users on older versions. | LLVM Feature | Stage | Description | |--------------|-------| ------------|