Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
97219d6
Minor grammar edits
Nov 3, 2025
9c1e4d8
Make var_declaration be child type of all variable decls
Nov 3, 2025
84d8cef
Grammar build
Nov 3, 2025
3b9aef5
Support for tensor expression declarations
Nov 3, 2025
0ca8dba
Extended parent and sibling search utils
Nov 3, 2025
213432f
Basic impure inspection
Nov 3, 2025
d94a657
Basic bind resolution
Nov 3, 2025
ed728a0
Method call support for binding resolver
Nov 3, 2025
ec909b5
Make use of binding resolver
Nov 3, 2025
cacc818
LHS only bindings for modifying methods
Nov 3, 2025
794764d
Global file search and results caching
Nov 3, 2025
7e708b3
Add diagnostics code
Nov 3, 2025
1a90440
Add impure inspection into inspection chain
Nov 3, 2025
e9ff132
Import BindResolver via @server
Nov 3, 2025
a642a97
Lint
Nov 3, 2025
c9bba46
Lint readonly type fields
Nov 3, 2025
f9faa3b
[Fix] bind tensor_vars_declaration node with var childnren only
Nov 6, 2025
a89e19d
[Fix] Check bound values in call-specific manner
Nov 6, 2025
14b2332
tuple_expression->typed_tuple
Nov 7, 2025
e26b04f
Nested tuple declarations
Nov 7, 2025
c34f2f0
Put expressions in tuple and tensor in named node
Nov 7, 2025
356a222
Recursive reference check
Nov 7, 2025
ad9b3ed
Grouped expression in assingment destructor
Nov 7, 2025
b30ac5c
Simplify nested expressions prior to binding
Nov 10, 2025
522bde3
Remove TODO unhandled assertion
Nov 11, 2025
c13a125
Recursively simplify vars lhs and grouped_expression
Nov 11, 2025
390db9a
Add optional type inference during return type binding
Nov 12, 2025
cc97bbb
Fix call ref assesment early termination
Nov 12, 2025
68c6e79
Make test runner generic
Nov 12, 2025
82a377d
Allow server to pre-load FunC stdlib
Nov 12, 2025
6f8cb73
Add impure inspection test
Nov 12, 2025
2d3742c
Revert "Grammar build"
Nov 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,30 @@
"parse:grammars:tolk": "cd ./server/src/languages/tolk/tree-sitter-tolk/ && tree-sitter parse -D --open-log main.tolk",
"test:e2e": "yarn test:e2e:tolk",
"test:e2e:compile": "tsc -p ./server/src/e2e/tsconfig.json",
"test:e2e:tolk": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts",
"test:e2e:tolk:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --update-snapshots",
"test:e2e:tolk:resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite resolving --update-snapshots",
"test:e2e:tolk:references:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite references --update-snapshots",
"test:e2e:tolk:rename:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite rename --update-snapshots",
"test:e2e:tolk:inspections:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite inspections --update-snapshots",
"test:e2e:tolk:foldings:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite foldings --update-snapshots",
"test:e2e:tolk:completion:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite completion --update-snapshots",
"test:e2e:tolk:completion-select:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite completion-select --update-snapshots",
"test:e2e:tolk:document-symbols:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite document-symbols --update-snapshots",
"test:e2e:tolk:inlay-hints:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite inlay-hints --update-snapshots",
"test:e2e:tolk:signature-help:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite signature-help --update-snapshots",
"test:e2e:tolk:intentions:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite intentions --update-snapshots",
"test:e2e:tolk:types:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite types --update-snapshots",
"test:e2e:tolk:types-2:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite types-2 --update-snapshots",
"test:e2e:tolk:documentation:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite documentation --update-snapshots",
"test:e2e:tolk:type-resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite type-resolving --update-snapshots",
"test:e2e:tolk:multifile-resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite multifile-resolving --update-snapshots",
"test:e2e:tolk:multifile-intentions:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite multifile-intentions --update-snapshots",
"test:e2e:tolk:multifile-completion-select:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite multifile-completion-select --update-snapshots",
"test:e2e:tolk:multifile-inspections:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite multifile-inspections --update-snapshots",
"test:e2e:tolk:compiler-tests:update": "yarn test:e2e:compile && ts-node server/src/e2e/runTolkTest.ts --suite compiler-tests --update-snapshots",
"test:e2e:tolk": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts",
"test:e2e:tolk:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --update-snapshots",
"test:e2e:tolk:resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite resolving --update-snapshots",
"test:e2e:tolk:references:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite references --update-snapshots",
"test:e2e:tolk:rename:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite rename --update-snapshots",
"test:e2e:tolk:inspections:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite inspections --update-snapshots",
"test:e2e:tolk:foldings:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite foldings --update-snapshots",
"test:e2e:tolk:completion:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite completion --update-snapshots",
"test:e2e:tolk:completion-select:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite completion-select --update-snapshots",
"test:e2e:tolk:document-symbols:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite document-symbols --update-snapshots",
"test:e2e:tolk:inlay-hints:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite inlay-hints --update-snapshots",
"test:e2e:tolk:signature-help:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite signature-help --update-snapshots",
"test:e2e:tolk:intentions:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite intentions --update-snapshots",
"test:e2e:tolk:types:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite types --update-snapshots",
"test:e2e:tolk:types-2:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite types-2 --update-snapshots",
"test:e2e:tolk:documentation:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite documentation --update-snapshots",
"test:e2e:tolk:type-resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite type-resolving --update-snapshots",
"test:e2e:tolk:multifile-resolving:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite multifile-resolving --update-snapshots",
"test:e2e:tolk:multifile-intentions:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite multifile-intentions --update-snapshots",
"test:e2e:tolk:multifile-completion-select:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite multifile-completion-select --update-snapshots",
"test:e2e:tolk:multifile-inspections:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite multifile-inspections --update-snapshots",
"test:e2e:tolk:compiler-tests:update": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --suite compiler-tests --verbose --update-snapshots",
"test:e2e:func": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --lang FunC --update-snapshots",
"test:e2e:func:impure-inspection": "yarn test:e2e:compile && ts-node server/src/e2e/runLangTest.ts --lang FunC --suite ImpureInspection --update-snapshots",
"pack:ls": "cd dist && npm pack",
"publish:ls": "cd dist && npm publish",
"build-server-package-and-publish": "yarn build && yarn pack:ls && yarn publish:ls",
Expand Down Expand Up @@ -652,7 +654,8 @@
"unused-parameter",
"unused-type-parameter",
"unused-variable",
"unused-import"
"unused-import",
"unused-impure"
]
},
"default": [],
Expand Down
54 changes: 54 additions & 0 deletions server/src/e2e/FunC/ImpureInspection.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as assert from "node:assert"

import * as vscode from "vscode"

import {TestCase} from "../common/TestParser"
import {BaseTestSuite} from "../common/BaseTestSuite"

suite("Impure inspection test suite", () => {
const testSuite = new (class extends BaseTestSuite {
public async getInspections(): Promise<string> {
await new Promise(resolve => setTimeout(resolve, 200))

const diagnostics = vscode.languages.getDiagnostics(this.document.uri)

const impureDiag = diagnostics
.filter(d => d.code == "unused-impure")
.sort((a, b) => {
if (a.range.start.line !== b.range.start.line) {
return a.range.start.line - b.range.start.line
}
return a.range.start.character - b.range.start.character
})

if (impureDiag.length === 0) {
return "no issues"
}

return impureDiag
.map(
d =>
`${d.range.start.line}:${d.range.start.character} to ${d.range.end.line}:${d.range.end.character}`,
)
.join("\n")
}

protected runTest(testFile: string, testCase: TestCase): void {
test(`Case: ${testCase.name}`, async () => {
await this.replaceDocumentText(testCase.input)
const inspectionRes = await this.getInspections()
assert.strictEqual(inspectionRes, testCase.expected)
})
}
})()
suiteSetup(async function () {
this.timeout(10_000)
await testSuite.suiteSetup()
})

setup(async () => testSuite.setup())
teardown(async () => testSuite.teardown())
suiteTeardown(() => testSuite.suiteTeardown())

testSuite.runTestsFromDirectory("impure-inspection")
})
153 changes: 153 additions & 0 deletions server/src/e2e/FunC/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// SPDX-License-Identifier: MIT
// Copyright © 2025 TON Studio
import * as path from "node:path"

import * as Mocha from "mocha"
import {glob} from "glob"
import {Suite, Test} from "mocha"

// node.js 20+ builtin
const globSync = (globs: string[], options: {cwd: string}): string[] => {
return globs.flatMap(g => glob.sync(g, options))
}

interface TestFilterOptions {
readonly suite?: string
readonly testPattern?: string
readonly verbose?: boolean
}

function getFilterOptions(): TestFilterOptions {
return {
suite: process.env["TON_TEST_SUITE"],
testPattern: process.env["TON_TEST_PATTERN"],
verbose: process.env["TON_TEST_VERBOSE"] === "true",
}
}

function getTestFilePattern(options: TestFilterOptions): string {
if (options.suite) {
return `${options.suite}.test.js`
}
return "*.test.js"
}

function shouldIncludeTest(testName: string, options: TestFilterOptions): boolean {
if (options.testPattern) {
return testName.toLowerCase().includes(options.testPattern.toLowerCase())
}
return true
}

export async function run(): Promise<void> {
const options = getFilterOptions()

if (options.verbose) {
console.log("Test filter options:", options)
}

const mocha = new Mocha({
ui: "tdd",
color: true,
timeout: 20_000,
})

process.env["TON_TESTS"] = "true"
process.env["TEST_FUNC_STDLIB_PATH"] = "../server/src/e2e/FunC/stdlib"

const testsRoot = path.resolve(__dirname, ".")
const testFilePattern = getTestFilePattern(options)

if (options.verbose) {
console.log(`Looking for test files matching: ${testFilePattern}`)
console.log(`In directory: ${testsRoot}`)
}

return new Promise((resolve, reject) => {
glob(testFilePattern, {
cwd: testsRoot,
})
.then(files => {
files.sort((a, b) => {
if (a.includes("multifile-") && b.includes("multifile-")) {
return Number(a < b)
}
if (a.includes("multifile-") && !b.includes("multifile-")) {
return 1
}
if (!a.includes("multifile-") && b.includes("multifile-")) {
return -1
}
return Number(a < b)
})

if (files.length === 0) {
if (options.suite) {
console.error(`No test suite found matching: ${options.suite}`)
console.log("Available test suites:")
const allFiles = globSync(["*.test.js"], {cwd: testsRoot})
for (const file of allFiles) {
const suiteName = path.basename(file, ".test.js")
console.log(` - ${suiteName}`)
}
reject(new Error(`Test suite '${options.suite}' not found`))
} else {
reject(new Error("No test files found"))
return
}
}

if (options.verbose) {
console.log(`Found ${files.length} test file(s):`)
for (const file of files) {
console.log(` - ${file}`)
}
}

for (const f of files) {
mocha.addFile(path.resolve(testsRoot, f))
}

if (options.testPattern) {
const originalRun = mocha.run.bind(mocha)
mocha.run = function (callback: (failures: number) => void) {
const suite = this.suite
filterTestsRecursively(suite, options)
return originalRun(callback)
}
}

try {
mocha.run(failures => {
if (failures > 0) {
reject(new Error(`${failures} tests failed.`))
} else {
resolve()
}
})
} catch (error) {
reject(error instanceof Error ? error : new Error(String(error)))
}
})
.catch((error: unknown) => {
reject(error instanceof Error ? error : new Error(String(error)))
})
})
}

function filterTestsRecursively(suite: Suite, options: TestFilterOptions): void {
if (!options.testPattern) return

suite.tests = suite.tests.filter((test: Test) => shouldIncludeTest(test.title, options))
for (const childSuite of suite.suites) {
filterTestsRecursively(childSuite, options)
}
suite.suites = suite.suites.filter((childSuite: Suite) => hasTests(childSuite))
}

function hasTests(suite: Suite): boolean {
if (suite.tests.length > 0) {
return true
}
return suite.suites.some(childSuite => hasTests(childSuite))
}
Loading