diff --git a/server/src/e2e/tolk/testcases/completion/struct-instance.test b/server/src/e2e/tolk/testcases/completion/struct-instance.test index 8fb068ef..8636d819 100644 --- a/server/src/e2e/tolk/testcases/completion/struct-instance.test +++ b/server/src/e2e/tolk/testcases/completion/struct-instance.test @@ -160,3 +160,30 @@ fun main(foo: Foo = {}) {} ------------------------------------------------------------------------ 9 first : int of Foo 9 second : slice of Foo + +======================================================================== +Fields completion with Cell type +======================================================================== +struct Cell { + tvmCell: cell +} + +struct Inner { + bar: int +} + +struct Data { + foo: Cell +} + +fun test() { + Data { + foo: In, + } +} +------------------------------------------------------------------------ +21 InMessage {} +21 InMessageBounced {} +21 Inner {} +21 StateInit {} +14 Inner {}.toCell() diff --git a/server/src/e2e/tolk/testcases/intentions/FillFieldsStructInit.test b/server/src/e2e/tolk/testcases/intentions/FillFieldsStructInit.test index 98ee24e2..9416996b 100644 --- a/server/src/e2e/tolk/testcases/intentions/FillFieldsStructInit.test +++ b/server/src/e2e/tolk/testcases/intentions/FillFieldsStructInit.test @@ -432,3 +432,33 @@ fun foo() { body: null, }); } + +======================================================================== +@intention Fill all fields... +Struct with Cell field +======================================================================== +struct Inner { + bar: int +} + +struct Data { + foo: Cell +} + +fun test() { + Data {} +} +------------------------------------------------------------------------ +struct Inner { + bar: int +} + +struct Data { + foo: Cell +} + +fun test() { + Data { + foo: Inner {}.toCell(), + } +} diff --git a/server/src/languages/tolk/completion/CompletionContext.ts b/server/src/languages/tolk/completion/CompletionContext.ts index 4809bc59..ea412ba6 100644 --- a/server/src/languages/tolk/completion/CompletionContext.ts +++ b/server/src/languages/tolk/completion/CompletionContext.ts @@ -21,6 +21,7 @@ export class CompletionContext { public isAnnotationName: boolean = false public expectMatchArm: boolean = false public catchVariable: boolean = false + public fieldInit: boolean = false // struct fields public inNameOfFieldInit: boolean = false @@ -59,6 +60,13 @@ export class CompletionContext { this.catchVariable = true } + if (parent.type === "instance_argument") { + const value = parent.childForFieldName("value") + if (value?.equals(element.node)) { + this.fieldInit = true + } + } + if (parent.type === "binary_operator" && parent.parent?.type === "match_arm") { // match (a) { // diff --git a/server/src/languages/tolk/completion/index.ts b/server/src/languages/tolk/completion/index.ts index 829928a6..f62bf09f 100644 --- a/server/src/languages/tolk/completion/index.ts +++ b/server/src/languages/tolk/completion/index.ts @@ -32,6 +32,7 @@ import {ExpressionSnippetsCompletionProvider} from "@server/languages/tolk/compl import {MatchArmsCompletionProvider} from "@server/languages/tolk/completion/providers/MatchArmsCompletionProvider" import {CompletionItemAdditionalInformation} from "@server/completion/CompletionItemAdditionalInformation" import {StorageCompletionProvider} from "@server/languages/tolk/completion/providers/StorageCompletionProvider" +import {FieldInitCompletionProvider} from "@server/languages/tolk/completion/providers/FieldInitCompletionProvider" export async function provideTolkCompletion( file: TolkFile, @@ -112,6 +113,7 @@ export async function provideTolkCompletion( new VariableSizeTypeCompletionProvider(), new MatchArmsCompletionProvider(ref), new StorageCompletionProvider(), + new FieldInitCompletionProvider(), ] for (const provider of providers) { diff --git a/server/src/languages/tolk/completion/providers/FieldInitCompletionProvider.ts b/server/src/languages/tolk/completion/providers/FieldInitCompletionProvider.ts new file mode 100644 index 00000000..306f6fa3 --- /dev/null +++ b/server/src/languages/tolk/completion/providers/FieldInitCompletionProvider.ts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2025 TON Core +import type {CompletionProvider} from "@server/completion/CompletionProvider" +import {CompletionItemKind, InsertTextFormat} from "vscode-languageserver-types" +import type {CompletionContext} from "@server/languages/tolk/completion/CompletionContext" +import {CompletionResult, CompletionWeight} from "@server/completion/WeightedCompletionItem" +import {Reference} from "@server/languages/tolk/psi/Reference" +import {NamedNode} from "@server/languages/tolk/psi/TolkNode" +import {typeOf} from "@server/languages/tolk/type-inference" +import {InstantiationTy, StructTy} from "@server/languages/tolk/types/ty" + +export class FieldInitCompletionProvider implements CompletionProvider { + public isAvailable(ctx: CompletionContext): boolean { + return ctx.fieldInit + } + + public addCompletion(ctx: CompletionContext, result: CompletionResult): void { + const instanceArgument = ctx.element.parentOfType("instance_argument") + if (!instanceArgument) return + + const fieldName = instanceArgument.childForFieldName("name") + if (!fieldName) return + + const field = Reference.resolve(new NamedNode(fieldName, ctx.element.file)) + if (!field) return + + const fieldType = typeOf(field.node, field.file) + if (!fieldType) return + + if ( + fieldType instanceof InstantiationTy && + fieldType.types.length > 0 && + fieldType.innerTy.name() === "Cell" && + fieldType.types[0] instanceof StructTy + ) { + // Cell => Foo{}.toCell() + const argTy = fieldType.types[0] + + result.add({ + label: argTy.name() + " {}.toCell()", + kind: CompletionItemKind.Snippet, + insertTextFormat: InsertTextFormat.Snippet, + insertText: argTy.name() + " {$0}.toCell()", + weight: CompletionWeight.CONTEXT_ELEMENT, + }) + } + } +} diff --git a/server/src/languages/tolk/intentions/FillFieldsStructInit.ts b/server/src/languages/tolk/intentions/FillFieldsStructInit.ts index c768fc2c..4001d7b0 100644 --- a/server/src/languages/tolk/intentions/FillFieldsStructInit.ts +++ b/server/src/languages/tolk/intentions/FillFieldsStructInit.ts @@ -15,6 +15,7 @@ import { BytesNTy, CoinsTy, FieldsOwnerTy, + InstantiationTy, IntTy, NullTy, StructTy, @@ -231,6 +232,17 @@ export class FillStructInitBase implements Intention { return this.typeDefaultValue(type.innerTy) } + if (type instanceof InstantiationTy) { + if ( + type.innerTy instanceof StructTy && + type.innerTy.name() === "Cell" && + type.types.length > 0 + ) { + return this.typeDefaultValue(type.types[0]) + ".toCell()" + } + return this.typeDefaultValue(type.innerTy) + } + return "null" } }