Skip to content

Commit 327e942

Browse files
authored
feat(completion): add as keyword completion (#158)
Fixes #150
1 parent d9ebc68 commit 327e942

11 files changed

+4272
-3909
lines changed

server/src/completion/CompletionContext.ts

+9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export class CompletionContext {
2929
isMessageContext: boolean = false
3030
isBouncedMessage: boolean = false
3131
isInitOfName: boolean = false
32+
afterFieldType: boolean = false
3233

3334
contextTy: Ty | null = null
3435

@@ -115,6 +116,13 @@ export class CompletionContext {
115116
if (type) {
116117
this.contextTy = TypeInferer.inferType(new Expression(type, this.element.file))
117118
}
119+
120+
const anchor = parent.childForFieldName("_completion_anchor")
121+
if (anchor && element.node.equals(anchor)) {
122+
this.afterFieldType = true
123+
this.isExpression = false
124+
this.isStatement = false
125+
}
118126
}
119127

120128
if (element.node.type === "type_identifier") {
@@ -263,6 +271,7 @@ export class CompletionContext {
263271
!this.inNameOfFieldInit &&
264272
!this.inTraitList &&
265273
!this.inParameter &&
274+
!this.afterFieldType &&
266275
!this.isInitOfName
267276
)
268277
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {CompletionProvider} from "@server/completion/CompletionProvider"
2+
import {CompletionItemKind, InsertTextFormat} from "vscode-languageserver-types"
3+
import {CompletionContext} from "@server/completion/CompletionContext"
4+
import {CompletionResult, CompletionWeight} from "@server/completion/WeightedCompletionItem"
5+
6+
export class AsKeywordCompletionProvider implements CompletionProvider {
7+
isAvailable(ctx: CompletionContext): boolean {
8+
return ctx.afterFieldType
9+
}
10+
11+
addCompletion(_ctx: CompletionContext, result: CompletionResult): void {
12+
result.add({
13+
label: "as",
14+
labelDetails: {
15+
detail: " type",
16+
},
17+
kind: CompletionItemKind.Keyword,
18+
insertText: "as $0",
19+
insertTextFormat: InsertTextFormat.Snippet,
20+
weight: CompletionWeight.CONTEXT_ELEMENT,
21+
})
22+
}
23+
}

server/src/completion/providers/ReferenceCompletionProvider.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class ReferenceCompletionProvider implements CompletionProvider {
2020
!ctx.topLevelInStructOrMessage &&
2121
!ctx.topLevel &&
2222
!ctx.inTlbSerialization &&
23+
!ctx.afterFieldType &&
2324
!ctx.inParameter
2425
)
2526
}

server/src/completion/providers/TlbSerializationCompletionProvider.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ export class TlbSerializationCompletionProvider implements CompletionProvider {
3737
const type = field.typeNode()?.type()
3838
if (!type) return
3939

40+
const semicolonPart = !ctx.beforeSemicolon ? ";" : ""
41+
4042
const typeName = type.name()
4143
if (typeName === "Cell" || typeName === "Slice" || typeName === "Builder") {
4244
result.add({
4345
label: "remaining",
4446
kind: CompletionItemKind.Keyword,
45-
insertText: "remaining",
47+
insertText: `remaining${semicolonPart}`,
4648
weight: CompletionWeight.CONTEXT_ELEMENT,
4749
})
4850
return
@@ -54,7 +56,9 @@ export class TlbSerializationCompletionProvider implements CompletionProvider {
5456
label: type,
5557
kind: CompletionItemKind.Keyword,
5658
insertTextFormat: InsertTextFormat.Snippet,
57-
insertText: type.includes("{X}") ? type.replace("{X}", "$1") : type,
59+
insertText: type.includes("{X}")
60+
? type.replace("{X}", "$1")
61+
: type + semicolonPart,
5862
weight: CompletionWeight.CONTEXT_ELEMENT,
5963
})
6064
}

server/src/e2e/suite/testcases/completion/tlb-serialization.test

+33
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,36 @@ struct Transfer {
7272
}
7373
------------------------------------------------------------------------
7474
13 remaining
75+
76+
========================================================================
77+
TL-B serialization as
78+
========================================================================
79+
primitive Builder;
80+
81+
struct Transfer {
82+
value: Builder <caret>;
83+
}
84+
------------------------------------------------------------------------
85+
13 as type
86+
87+
========================================================================
88+
TL-B serialization as 2
89+
========================================================================
90+
primitive Builder;
91+
92+
struct Transfer {
93+
value: Builder <caret>
94+
}
95+
------------------------------------------------------------------------
96+
13 as type
97+
98+
========================================================================
99+
TL-B serialization as 3
100+
========================================================================
101+
primitive Builder;
102+
103+
contract Transfer {
104+
value: Builder <caret>
105+
}
106+
------------------------------------------------------------------------
107+
13 as type

server/src/server.ts

+2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import {AddImport} from "@server/intentions/AddImport"
9898
import {NotImportedSymbolInspection} from "@server/inspections/NotImportedSymbolInspection"
9999
import {FillAllStructInit, FillRequiredStructInit} from "@server/intentions/FillAllStructInit"
100100
import {generateInitDoc, generateReceiverDoc} from "@server/documentation/receivers_documentation"
101+
import {AsKeywordCompletionProvider} from "@server/completion/providers/AsKeywordCompletionProvider"
101102

102103
/**
103104
* Whenever LS is initialized.
@@ -688,6 +689,7 @@ connection.onInitialize(async (params: lsp.InitializeParams): Promise<lsp.Initia
688689
const providers: CompletionProvider[] = [
689690
new SnippetsCompletionProvider(),
690691
new KeywordsCompletionProvider(),
692+
new AsKeywordCompletionProvider(),
691693
new MapTypeCompletionProvider(),
692694
new BouncedTypeCompletionProvider(),
693695
new ContractDeclCompletionProvider(),

tree-sitter-tact/grammar.js

+1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ module.exports = grammar({
299299
seq(
300300
":",
301301
field("type", $._type),
302+
field("_completion_anchor", optional($.identifier)),
302303
field("tlb", optional($.tlb_serialization)),
303304
optional(seq("=", field("value", $._expression))),
304305
),

tree-sitter-tact/src/grammar.json

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tree-sitter-tact/src/node-types.json

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)