Skip to content

Commit 88a6b20

Browse files
committed
feat(tolk): support contract declaration from Tolk 1.3
Fixes #260
1 parent be98b1f commit 88a6b20

23 files changed

Lines changed: 34209 additions & 32590 deletions

File tree

editors/code/src/languages/syntaxes/tolk.tmLanguage.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
},
5252
{
5353
"name": "keyword.other",
54-
"match": "\\b(import|export|true|false|null|redef|mutate|tolk|as|is|!is|private|readonly|string)\\b"
54+
"match": "\\b(import|export|true|false|null|redef|mutate|tolk|as|is|!is|private|readonly|string|contract)\\b"
5555
},
5656
{
5757
"name": "keyword.other",
@@ -81,7 +81,7 @@
8181
},
8282
{
8383
"name": "storage.modifier",
84-
"match": "\\b(global|const|var|val|fun|get|struct)\\b"
84+
"match": "\\b(global|const|var|val|fun|get|struct|contract)\\b"
8585
},
8686
{
8787
"name": "entity.name.type",

server/src/e2e/tolk/testcases/completion-select/top-level.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,16 @@ Method name completion with all signature
111111
fun int.pa<caret>() {}
112112
------------------------------------------------------------------------
113113
fun int.packToBuilder<caret>() {}
114+
115+
========================================================================
116+
Contract completion
117+
========================================================================
118+
contract<caret>
119+
------------------------------------------------------------------------
120+
contract Name<caret> {
121+
author: ""
122+
version: "1.0.0"
123+
description: "My TON contract"
124+
incomingMessages: AllowedMessages
125+
storage: Storage
126+
}

server/src/e2e/tolk/testcases/completion/constants.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ fun test() {
2222
}
2323
------------------------------------------------------------------------
2424
20 CONSTANT_BAR: bool = true
25-
20 CONSTANT_FOO: slice = ""
25+
20 CONSTANT_FOO: string = ""
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
========================================================================
2+
Contract fields completion
3+
========================================================================
4+
contract MyContract {
5+
<caret>
6+
}
7+
------------------------------------------------------------------------
8+
4 author: Author of the contract
9+
4 description: Description of the contract
10+
4 forceAbiExport: List of symbols to additionally export to ABI
11+
4 incomingExternal: Allowed incoming external messages type
12+
4 incomingMessages: Allowed incoming messages type
13+
4 storage: Persistent storage structure
14+
4 storageAtDeployment: Storage structure at deployment
15+
4 symbolsNamespace: Namespace for contract symbols
16+
4 version: Version of the contract
17+
18+
========================================================================
19+
Contract fields completion — existing fields excluded
20+
========================================================================
21+
contract MyContract {
22+
author: "me",
23+
<caret>
24+
}
25+
------------------------------------------------------------------------
26+
4 description: Description of the contract
27+
4 forceAbiExport: List of symbols to additionally export to ABI
28+
4 incomingExternal: Allowed incoming external messages type
29+
4 incomingMessages: Allowed incoming messages type
30+
4 storage: Persistent storage structure
31+
4 storageAtDeployment: Storage structure at deployment
32+
4 symbolsNamespace: Namespace for contract symbols
33+
4 version: Version of the contract

server/src/e2e/tolk/testcases/completion/local.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fun foo() {
99
}
1010
------------------------------------------------------------------------
1111
5 some int
12-
5 someOther slice
12+
5 someOther string
1313

1414
========================================================================
1515
Variables completion from tuple declaration
@@ -21,7 +21,7 @@ fun foo() {
2121
}
2222
------------------------------------------------------------------------
2323
5 some int
24-
5 someOther slice
24+
5 someOther string
2525

2626
========================================================================
2727
Variable completion from catch clause
@@ -106,7 +106,7 @@ fun foo() {
106106
}
107107
------------------------------------------------------------------------
108108
5 some int
109-
5 someOther slice
109+
5 someOther string
110110

111111
========================================================================
112112
No type parameters completion as value

server/src/e2e/tolk/testcases/completion/top-level.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Top level completion
44
<caret>
55
------------------------------------------------------------------------
66
13 const FOO: <type> = <value>
7+
13 contract Name {}
78
13 enum Name {}
89
13 fun name() {}
910
13 get fun name() {}
@@ -30,6 +31,7 @@ fun foo() {}
3031
<caret>
3132
------------------------------------------------------------------------
3233
13 const FOO: <type> = <value>
34+
13 contract Name {}
3335
13 enum Name {}
3436
13 fun name() {}
3537
13 get fun name() {}
@@ -58,6 +60,7 @@ import "./file.tolk";
5860
fun foo() {}
5961
------------------------------------------------------------------------
6062
13 const FOO: <type> = <value>
63+
13 contract Name {}
6164
13 enum Name {}
6265
13 fun name() {}
6366
13 get fun name() {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
========================================================================
2+
Contract documentation
3+
========================================================================
4+
contract <caret>MyContract {
5+
author: "me",
6+
version: "1.0.0"
7+
}
8+
------------------------------------------------------------------------
9+
```tolk
10+
contract MyContract {
11+
author: "me"
12+
version: "1.0.0"
13+
}
14+
```
15+
16+
========================================================================
17+
Contract field documentation
18+
========================================================================
19+
contract MyContract {
20+
<caret>author: "me",
21+
version: "1.0.0"
22+
}
23+
------------------------------------------------------------------------
24+
```tolk
25+
contract MyContract
26+
author
27+
```
28+
Author of the contract.

server/src/languages/tolk/completion/CompletionContext.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export class CompletionContext {
1515
public isStatement: boolean = false
1616
public topLevel: boolean = false
1717
public structTopLevel: boolean = false
18+
public contractTopLevel: boolean = false
1819
public afterDot: boolean = false
1920
public beforeParen: boolean = false
2021
public beforeSemicolon: boolean = false
@@ -140,12 +141,14 @@ export class CompletionContext {
140141
const grand = parent.parent
141142
if (grand.type === "struct_body") {
142143
this.structTopLevel = true
144+
} else if (grand.type === "contract_body") {
145+
this.contractTopLevel = true
143146
} else {
144147
this.topLevel = true
145148
}
146149
}
147150

148-
if (!this.topLevel && !this.structTopLevel) {
151+
if (!this.topLevel && !this.structTopLevel && !this.contractTopLevel) {
149152
if (parent.type === "expression_statement") {
150153
this.isStatement = true
151154
} else {
@@ -196,6 +199,7 @@ export class CompletionContext {
196199
!this.inNameOfFieldInit &&
197200
!this.insideImport &&
198201
!this.structTopLevel &&
202+
!this.contractTopLevel &&
199203
!this.expectMatchArm &&
200204
!this.catchVariable &&
201205
!this.isFunctionName &&

server/src/languages/tolk/completion/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {FieldInitCompletionProvider} from "@server/languages/tolk/completion/pro
3737
import {FunctionNameCompletionProvider} from "@server/languages/tolk/completion/providers/FunctionNameCompletionProvider"
3838
import {StructFieldModifiersCompletionProvider} from "@server/languages/tolk/completion/providers/StructFieldModifiersCompletionProvider"
3939
import {EnumCompletionProvider} from "@server/languages/tolk/completion/providers/EnumCompletionProvider"
40+
import {ContractFieldCompletionProvider} from "@server/languages/tolk/completion/providers/ContractFieldCompletionProvider"
4041
import {ActonWalletNameCompletionProvider} from "@server/languages/tolk/completion/providers/ActonWalletNameCompletionProvider"
4142
import {ActonContractIdCompletionProvider} from "@server/languages/tolk/completion/providers/ActonContractIdCompletionProvider"
4243
import {ActonGetMethodCompletionProvider} from "@server/languages/tolk/completion/providers/ActonGetMethodCompletionProvider"
@@ -124,6 +125,7 @@ export async function provideTolkCompletion(
124125
new FunctionNameCompletionProvider(),
125126
new StructFieldModifiersCompletionProvider(),
126127
new EnumCompletionProvider(),
128+
new ContractFieldCompletionProvider(),
127129
]
128130

129131
for (const provider of providers) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright © 2025 TON Core
3+
import {CompletionItemKind, InsertTextFormat} from "vscode-languageserver-types"
4+
5+
import type {CompletionProvider} from "@server/completion/CompletionProvider"
6+
import type {CompletionContext} from "@server/languages/tolk/completion/CompletionContext"
7+
import {CompletionResult, CompletionWeight} from "@server/completion/WeightedCompletionItem"
8+
import {parentOfType} from "@server/psi/utils"
9+
10+
export class ContractFieldCompletionProvider implements CompletionProvider<CompletionContext> {
11+
public isAvailable(ctx: CompletionContext): boolean {
12+
return ctx.contractTopLevel
13+
}
14+
15+
public addCompletion(ctx: CompletionContext, result: CompletionResult): void {
16+
const contract = parentOfType(ctx.element.node, "contract_declaration")
17+
if (!contract) return
18+
19+
const body = contract.childForFieldName("body")
20+
if (!body) return
21+
22+
const existingFields: Set<string> = new Set()
23+
for (const child of body.children) {
24+
if (child?.type === "contract_field") {
25+
const name = child.childForFieldName("name")?.text
26+
if (name) existingFields.add(name)
27+
}
28+
}
29+
30+
const fields: Record<string, string> = {
31+
author: "Author of the contract",
32+
version: "Version of the contract",
33+
description: "Description of the contract",
34+
symbolsNamespace: "Namespace for contract symbols",
35+
incomingMessages: "Allowed incoming messages type",
36+
incomingExternal: "Allowed incoming external messages type",
37+
storage: "Persistent storage structure",
38+
storageAtDeployment: "Storage structure at deployment",
39+
forceAbiExport: "List of symbols to additionally export to ABI",
40+
}
41+
42+
for (const [field, description] of Object.entries(fields)) {
43+
if (existingFields.has(field)) continue
44+
45+
result.add({
46+
label: field,
47+
labelDetails: {
48+
detail: `: ${description}`,
49+
},
50+
kind: CompletionItemKind.Field,
51+
insertText: `${field}: $0`,
52+
insertTextFormat: InsertTextFormat.Snippet,
53+
weight: CompletionWeight.CONTEXT_ELEMENT,
54+
})
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)