-
Notifications
You must be signed in to change notification settings - Fork 41
/
lens.ts
103 lines (96 loc) · 3.65 KB
/
lens.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import * as vscode from "vscode";
import { Cache } from "../cache";
import { OpenApi30, Swagger, BundledSwaggerOrOasSpec, isOpenapi, deref } from "@xliic/openapi";
import { getLocation } from "@xliic/preserving-json-yaml-parser";
import { getOpenApiVersion } from "../parsers";
import { OpenApiVersion } from "../types";
export class TryItCodelensProvider implements vscode.CodeLensProvider {
private lenses: Record<string, vscode.CodeLens[]> = {};
constructor(private cache: Cache) {}
async provideCodeLenses(
document: vscode.TextDocument,
token: vscode.CancellationToken
): Promise<vscode.CodeLens[]> {
const parsed = this.cache.getParsedDocument(document);
const version = getOpenApiVersion(parsed);
if (parsed && version !== OpenApiVersion.Unknown) {
const result: vscode.CodeLens[] = [];
const oas = parsed as unknown as BundledSwaggerOrOasSpec;
const operations = isOpenapi(oas) ? OpenApi30.getOperations(oas) : Swagger.getOperations(oas);
for (const [path, method, operation] of operations) {
const tryOperationLens = operationLens(document, oas, path, method);
if (tryOperationLens) {
result.push(tryOperationLens);
}
// TODO examples in swagger
if (isOpenapi(oas)) {
result.push(
...operationExamplesLens(document, oas, path, method, operation as OpenApi30.Operation)
);
}
}
this.lenses[document.uri.toString()] = result;
}
return this.lenses[document.uri.toString()];
}
}
function operationLens(
document: vscode.TextDocument,
oas: BundledSwaggerOrOasSpec,
path: string,
method: string
): vscode.CodeLens | undefined {
const location = getLocation(oas.paths[path], method);
if (!location) {
return undefined;
}
const position = document.positionAt(location!.key!.start);
const line = document.lineAt(position.line + 1);
const range = new vscode.Range(
new vscode.Position(position.line + 1, line.firstNonWhitespaceCharacterIndex),
new vscode.Position(position.line + 1, line.range.end.character)
);
return new vscode.CodeLens(range, {
title: `Try it`,
tooltip: "Try this operation by sending a request",
command: "openapi.tryOperation",
arguments: [document, path, method],
});
}
function operationExamplesLens(
document: vscode.TextDocument,
oas: OpenApi30.BundledSpec,
path: string,
method: string,
operation: OpenApi30.Operation
): vscode.CodeLens[] {
const result = [];
const content = deref(oas, operation.requestBody)?.content;
for (const [mediaType, mediaTypeContent] of Object.entries(content || {})) {
const examples = mediaTypeContent.examples;
if (examples) {
for (const [name, exampleOrRef] of Object.entries(examples)) {
const location = getLocation(examples, name);
const example = deref(oas, exampleOrRef);
if (location && example?.value !== undefined) {
const position = document.positionAt(location!.key!.start);
const line = document.lineAt(position.line + 1);
const range = new vscode.Range(
new vscode.Position(position.line + 1, line.firstNonWhitespaceCharacterIndex),
new vscode.Position(position.line + 1, line.range.end.character)
);
result.push(
new vscode.CodeLens(range, {
title: `Try it`,
tooltip:
"Try this operation by sending a request, use this example for the request body",
command: "openapi.tryOperationWithExample",
arguments: [document, path, method, mediaType, example.value],
})
);
}
}
}
}
return result;
}