Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions editors/code/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ Node.js: ${info.environment.nodeVersion ?? "Unknown"}`
}
}
}),
vscode.commands.registerCommand("ton.copyToClipboard", (str: string) => {
void vscode.env.clipboard.writeText(str)
void vscode.window.showInformationMessage(`Copied ${str} to clipboard`)
}),
)
}

Expand Down
61 changes: 61 additions & 0 deletions server/src/languages/func/lens/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
// Copyright © 2025 TON Core
import * as lsp from "vscode-languageserver"
import {RecursiveVisitor} from "@server/visitor/visitor"
import {FuncFile} from "@server/languages/func/psi/FuncFile"
import {createHash} from "node:crypto"
import {crc32} from "@server/utils/crc32"
import {asLspRange} from "@server/utils/position"

export function collectFuncCodeLenses(file: FuncFile): lsp.CodeLens[] {
if (file.fromStdlib) {
// we don't need to count usages or show anything for stdlib symbols
return []
}

const result: lsp.CodeLens[] = []

RecursiveVisitor.visit(file.rootNode, (n): boolean => {
// "..."c
if (n.type === "number_string_literal") {
const numberTag = n.text.at(-1) ?? ""
const text = n.text.slice(1, -2)

let res: string
switch (numberTag) {
case "H": {
res = createHash("sha256").update(text).digest("hex")
break
}
case "h": {
res = createHash("sha256").update(text).digest().subarray(0, 8).toString("hex")
break
}
case "u": {
res = Buffer.from(text).toString("hex")
break
}
case "c": {
res = crc32(text).toString(16)
break
}
default: {
res = text
}
}

result.push({
range: asLspRange(n),
command: {
title: `Copy ${res} to clipboard`,
command: "ton.copyToClipboard",
arguments: [res],
},
})
}

return true
})

return result
}
20 changes: 19 additions & 1 deletion server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ import {
import {IndexingRootKind} from "@server/indexing/indexing"
import {FuncIndexingRoot} from "@server/languages/func/indexing-root"
import {formatTolkFile} from "@server/languages/tolk/format/format"
import {collectFuncCodeLenses} from "@server/languages/func/lens"

/**
* Whenever LS is initialized.
Expand Down Expand Up @@ -250,7 +251,7 @@ async function findTolkStdlib(settings: ServerSettings, rootDir: string): Promis
if (stdlibPath === null) {
console.error(
"Tolk standard library not found! Searched in:\n",
searchDirs.map(dir => path.join(rootDir, dir)).join("\n"),
searchDirs.map(dir => `- ${dir}`).join("\n"),
)

showErrorMessage(
Expand Down Expand Up @@ -971,6 +972,20 @@ connection.onInitialize(async (initParams: lsp.InitializeParams): Promise<lsp.In
},
)

connection.onRequest(
lsp.CodeLensRequest.type,
async (params: lsp.CodeLensParams): Promise<lsp.CodeLens[] | null> => {
const uri = params.textDocument.uri

if (isFuncFile(uri)) {
const file = await findFuncFile(uri)
return collectFuncCodeLenses(file)
}

return null
},
)

connection.onRequest(
lsp.ExecuteCommandRequest.type,
async (params: lsp.ExecuteCommandParams): Promise<string | null> => {
Expand Down Expand Up @@ -1082,6 +1097,9 @@ connection.onInitialize(async (initParams: lsp.InitializeParams): Promise<lsp.In
renameProvider: {
prepareProvider: true,
},
codeLensProvider: {
resolveProvider: false,
},
hoverProvider: true,
inlayHintProvider: true,
referencesProvider: true,
Expand Down
24 changes: 24 additions & 0 deletions server/src/utils/crc32.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const POLYNOMIAL = -306_674_912

let crc32_table: Int32Array | undefined = undefined

export function crc32(str: string, crc: number = 0xff_ff_ff_ff): number {
const bytes = Buffer.from(str)
if (crc32_table === undefined) {
calcTable()
}
const table = crc32_table ?? new Int32Array(crc)
for (const byte of bytes) {
crc = table[(crc ^ byte) & 0xff] ^ (crc >>> 8)
}
return (crc ^ -1) >>> 0
}

function calcTable(): void {
crc32_table = new Int32Array(256)
for (let i = 0; i < 256; i++) {
let r = i
for (let bit = 8; bit > 0; --bit) r = r & 1 ? (r >>> 1) ^ POLYNOMIAL : r >>> 1
crc32_table[i] = r
}
}
Loading