Skip to content

Commit 277f018

Browse files
authored
feature(server) - Add support for Ref in hover and autocomplete (#248)
* Support Ref functions for hover/autocomplete
1 parent b393cf0 commit 277f018

File tree

8 files changed

+537
-86
lines changed

8 files changed

+537
-86
lines changed

client/src/test/suite/completion.test.ts

Lines changed: 139 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,78 +2,81 @@ import * as vscode from "vscode";
22
import assert = require("assert");
33
import { getDocUri, activate } from "./helper";
44

5-
suite("Should code complete", () => {
6-
const docUri = getDocUri("completion", "completion.yaml");
5+
const intrinsics = [
6+
{
7+
label: "!And",
8+
kind: 11,
9+
},
10+
{
11+
label: "!Base64",
12+
kind: 11,
13+
},
14+
{
15+
label: "!Cidr",
16+
kind: 11,
17+
},
18+
{
19+
label: "!Equals",
20+
kind: 11,
21+
},
22+
{
23+
label: "!FindInMap",
24+
kind: 11,
25+
},
26+
{
27+
label: "!GetAtt",
28+
kind: 11,
29+
},
30+
{
31+
label: "!GetAZs",
32+
kind: 11,
33+
},
34+
{
35+
label: "!If",
36+
kind: 11,
37+
},
38+
{
39+
label: "!ImportValue",
40+
kind: 11,
41+
},
42+
{
43+
label: "!Join",
44+
kind: 11,
45+
},
46+
{
47+
label: "!Not",
48+
kind: 11,
49+
},
50+
{
51+
label: "!Or",
52+
kind: 11,
53+
},
54+
{
55+
label: "!Ref",
56+
kind: 11,
57+
},
58+
{
59+
label: "!Select",
60+
kind: 11,
61+
},
62+
{
63+
label: "!Split",
64+
kind: 11,
65+
},
66+
{
67+
label: "!Sub",
68+
kind: 11,
69+
},
70+
];
771

72+
suite("Should code complete", () => {
873
test("Complete on empty template", async () => {
74+
const docUri = getDocUri("completion", "completion.yaml");
975
await activate(docUri);
1076

1177
await testCompletion(docUri, new vscode.Position(0, 0), {
1278
items: [
13-
{
14-
label: "!And",
15-
kind: 11,
16-
},
17-
{
18-
label: "!Base64",
19-
kind: 11,
20-
},
21-
{
22-
label: "!Cidr",
23-
kind: 11,
24-
},
25-
{
26-
label: "!Equals",
27-
kind: 11,
28-
},
29-
{
30-
label: "!FindInMap",
31-
kind: 11,
32-
},
33-
{
34-
label: "!GetAtt",
35-
kind: 11,
36-
},
37-
{
38-
label: "!GetAZs",
39-
kind: 11,
40-
},
41-
{
42-
label: "!If",
43-
kind: 11,
44-
},
45-
{
46-
label: "!ImportValue",
47-
kind: 11,
48-
},
49-
{
50-
label: "!Join",
51-
kind: 11,
52-
},
53-
{
54-
label: "!Not",
55-
kind: 11,
56-
},
57-
{
58-
label: "!Or",
59-
kind: 11,
60-
},
61-
{
62-
label: "!Ref",
63-
kind: 11,
64-
},
65-
{
66-
label: "!Select",
67-
kind: 11,
68-
},
69-
{
70-
label: "!Split",
71-
kind: 11,
72-
},
73-
{
74-
label: "!Sub",
75-
kind: 11,
76-
},
79+
...intrinsics,
7780
{
7881
label: "object",
7982
kind: 6,
@@ -125,6 +128,76 @@ suite("Should code complete", () => {
125128
],
126129
});
127130
});
131+
132+
test("Complete on ref", async () => {
133+
const docUri = getDocUri("completion", "completion2.yaml");
134+
await activate(docUri);
135+
136+
const completion_intrinsics = intrinsics.filter(
137+
(intrinsic) => intrinsic.label !== "!Ref"
138+
);
139+
140+
await testCompletion(docUri, new vscode.Position(17, 19), {
141+
items: [
142+
...completion_intrinsics,
143+
{
144+
label: "Subnet1",
145+
kind: 11,
146+
},
147+
{
148+
label: "Subnet2",
149+
kind: 11,
150+
},
151+
{
152+
label: "RouteTable1",
153+
kind: 11,
154+
},
155+
{
156+
label: "Subnet1RouteTable1",
157+
kind: 11,
158+
},
159+
{
160+
label: "Vpc",
161+
kind: 11,
162+
},
163+
],
164+
});
165+
});
166+
167+
test("Complete with full ref", async () => {
168+
const docUri = getDocUri("completion", "completion2.yaml");
169+
await activate(docUri);
170+
171+
const completion_intrinsics = intrinsics.filter(
172+
(intrinsic) => intrinsic.label !== "!Ref"
173+
);
174+
175+
await testCompletion(docUri, new vscode.Position(21, 22), {
176+
items: [
177+
...completion_intrinsics,
178+
{
179+
label: "!Ref Subnet1",
180+
kind: 11,
181+
},
182+
{
183+
label: "!Ref Subnet2",
184+
kind: 11,
185+
},
186+
{
187+
label: "!Ref RouteTable1",
188+
kind: 11,
189+
},
190+
{
191+
label: "!Ref Subnet1RouteTable1",
192+
kind: 11,
193+
},
194+
{
195+
label: "!Ref Vpc",
196+
kind: 11,
197+
},
198+
],
199+
});
200+
});
128201
});
129202

130203
export async function testCompletion(
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
Parameters:
3+
Vpc:
4+
Type: AWS::EC2::VPC::Id
5+
Resources:
6+
Subnet1:
7+
Type: AWS::EC2::Subnet
8+
Properties:
9+
VpcId: !Ref Vpc
10+
Subnet2:
11+
Type: AWS::EC2::Subnet
12+
Properties:
13+
VpcId:
14+
Ref: V
15+
RouteTable1:
16+
Type: AWS::EC2::RouteTable
17+
Properties:
18+
VpcId: !Ref V
19+
Subnet1RouteTable1:
20+
Type: AWS::EC2::SubnetRouteTableAssociation
21+
Properties:
22+
RouteTableId: !R
23+
SubnetId: !Ref Subnet1
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
Parameters:
3+
Vpc:
4+
Type: AWS::EC2::VPC::Id
5+
Resources:
6+
Subnet1:
7+
Type: AWS::EC2::Subnet
8+
Properties:
9+
VpcId: !Ref Vpc
10+
Subnet2:
11+
Type: AWS::EC2::Subnet
12+
Properties:
13+
VpcId:
14+
Ref: Vpc
15+
RouteTable1:
16+
Type: AWS::EC2::RouteTable
17+
Properties:
18+
VpcId: !Ref Vpc
19+
Subnet1RouteTable1:
20+
Type: AWS::EC2::SubnetRouteTableAssociation
21+
Properties:
22+
RouteTableId: !Ref RouteTable1
23+
SubnetId:
24+
Ref: Subnet1
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as vscode from "vscode";
2+
import assert = require("assert");
3+
import { getDocUri, activate } from "./helper";
4+
5+
suite("Should hover", () => {
6+
test("Hover on !Ref to parameter", async () => {
7+
const docUri = getDocUri("hover", "hover.yaml");
8+
await activate(docUri);
9+
10+
await testHover(
11+
docUri,
12+
new vscode.Position(17, 20),
13+
"\n```\n(Parameter) Vpc: AWS::EC2::VPC::Id\n```\n"
14+
);
15+
});
16+
test("Hover on !Ref to resource", async () => {
17+
const docUri = getDocUri("hover", "hover.yaml");
18+
await activate(docUri);
19+
20+
await testHover(
21+
docUri,
22+
new vscode.Position(21, 31),
23+
"\n```\n(Resource) RouteTable1: AWS::EC2::RouteTable\n```\n"
24+
);
25+
});
26+
test("Hover on Ref: to resource", async () => {
27+
const docUri = getDocUri("hover", "hover.yaml");
28+
await activate(docUri);
29+
30+
await testHover(
31+
docUri,
32+
new vscode.Position(23, 17),
33+
"\n```\n(Resource) Subnet1: AWS::EC2::Subnet\n```\n"
34+
);
35+
});
36+
test("Hover on Ref: to parameter", async () => {
37+
const docUri = getDocUri("hover", "hover.yaml");
38+
await activate(docUri);
39+
40+
await testHover(
41+
docUri,
42+
new vscode.Position(13, 15),
43+
"\n```\n(Parameter) Vpc: AWS::EC2::VPC::Id\n```\n"
44+
);
45+
});
46+
});
47+
48+
export async function testHover(
49+
docUri: vscode.Uri,
50+
position: vscode.Position,
51+
expectedHover: string
52+
): Promise<void> {
53+
// Executing the command `vscode.executeHoverProvider` to simulate triggering hover
54+
const actualHovers = (await vscode.commands.executeCommand(
55+
"vscode.executeHoverProvider",
56+
docUri,
57+
position
58+
)) as vscode.Hover[];
59+
60+
const actualHover = actualHovers[0];
61+
const gotMessage = (<vscode.MarkdownString>actualHover.contents[0]).value;
62+
assert.equal(expectedHover, gotMessage);
63+
}

server/src/cfnSettings.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,32 +57,25 @@ export class SettingsState extends YamlSettingsState {
5757
constructor() {
5858
super();
5959
this.customTags = [
60-
"!And",
6160
"!And sequence",
62-
"!If",
6361
"!If sequence",
64-
"!Not",
6562
"!Not sequence",
66-
"!Equals",
6763
"!Equals sequence",
68-
"!Or",
6964
"!Or sequence",
70-
"!FindInMap",
7165
"!FindInMap sequence",
72-
"!Base64",
73-
"!Join",
66+
"!Base64 scalar",
7467
"!Join sequence",
75-
"!Cidr",
76-
"!Ref",
77-
"!Sub",
68+
"!Cidr sequence",
69+
"!Ref scalar",
70+
"!Sub scalar",
7871
"!Sub sequence",
79-
"!GetAtt",
80-
"!GetAZs",
81-
"!ImportValue",
82-
"!ImportValue sequence",
83-
"!Select",
72+
"!GetAtt scalar",
73+
"!GetAtt sequence",
74+
"!GetAZs mapping",
75+
"!GetAZs scalar",
76+
"!ImportValue mapping",
77+
"!ImportValue scalar",
8478
"!Select sequence",
85-
"!Split",
8679
"!Split sequence",
8780
];
8881
this.schemaStoreEnabled = false;

0 commit comments

Comments
 (0)