vscode-apollo 1.20.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +27 -18
- package/.git-blame-ignore-revs +2 -0
- package/.nvmrc +1 -1
- package/.vscode/launch.json +9 -4
- package/.vscode/tasks.json +58 -16
- package/.vscodeignore +12 -1
- package/CHANGELOG.md +78 -0
- package/CODEOWNERS +4 -0
- package/README.md +97 -48
- package/graphql.configuration.json +5 -1
- package/images/marketplace/apollo-wordmark.png +0 -0
- package/jest.config.ts +14 -4
- package/jest.e2e.config.js +17 -0
- package/package.json +67 -68
- package/renovate.json +7 -0
- package/sampleWorkspace/clientSchema/apollo.config.cjs +10 -0
- package/sampleWorkspace/clientSchema/src/clientSchema.js +16 -0
- package/sampleWorkspace/clientSchema/src/test.js +18 -0
- package/sampleWorkspace/fixtures/starwarsSchema.graphql +299 -0
- package/sampleWorkspace/httpSchema/apollo.config.ts +8 -0
- package/sampleWorkspace/httpSchema/src/test.js +9 -0
- package/sampleWorkspace/localSchema/apollo.config.js +8 -0
- package/sampleWorkspace/localSchema/src/test.js +8 -0
- package/sampleWorkspace/localSchemaArray/apollo.config.js +12 -0
- package/sampleWorkspace/localSchemaArray/planets.graphql +20 -0
- package/sampleWorkspace/localSchemaArray/src/test.js +12 -0
- package/sampleWorkspace/sampleWorkspace.code-workspace +20 -0
- package/sampleWorkspace/spotifyGraph/apollo.config.mjs +5 -0
- package/sampleWorkspace/spotifyGraph/src/test.js +11 -0
- package/src/__e2e__/mockServer.js +117 -0
- package/src/__e2e__/mocks.js +13094 -0
- package/src/__e2e__/run.js +23 -0
- package/src/__e2e__/runTests.js +44 -0
- package/src/__e2e__/setup.js +1 -0
- package/src/__e2e__/vscode-environment.js +16 -0
- package/src/__e2e__/vscode.js +1 -0
- package/src/build.js +57 -0
- package/src/env/index.ts +0 -3
- package/src/extension.ts +251 -225
- package/src/language-server/__e2e__/clientSchema.e2e.ts +147 -0
- package/src/language-server/__e2e__/httpSchema.e2e.ts +21 -0
- package/src/language-server/__e2e__/localSchema.e2e.ts +25 -0
- package/src/language-server/__e2e__/localSchemaArray.e2e.ts +31 -0
- package/src/language-server/__e2e__/studioGraph.e2e.ts +65 -0
- package/src/language-server/__e2e__/utils.ts +151 -0
- package/src/language-server/__tests__/diagnostics.test.ts +8 -8
- package/src/language-server/__tests__/fileSet.test.ts +1 -1
- package/src/language-server/__tests__/fixtures/starwarsSchema.ts +2 -2
- package/src/language-server/config/__tests__/config.ts +22 -96
- package/src/language-server/config/__tests__/loadConfig.ts +97 -221
- package/src/language-server/config/__tests__/utils.ts +22 -29
- package/src/language-server/config/config.ts +221 -156
- package/src/language-server/config/loadConfig.ts +26 -153
- package/src/language-server/config/utils.ts +5 -16
- package/src/language-server/diagnostics.ts +17 -8
- package/src/language-server/document.ts +16 -16
- package/src/language-server/engine/index.ts +57 -39
- package/src/language-server/engine/operations/frontendUrlRoot.ts +9 -1
- package/src/language-server/engine/operations/schemaTagsAndFieldStats.ts +9 -1
- package/src/language-server/errors/__tests__/NoMissingClientDirectives.test.ts +10 -5
- package/src/language-server/errors/logger.ts +1 -1
- package/src/language-server/errors/validation.ts +20 -23
- package/src/language-server/fileSet.ts +10 -12
- package/src/language-server/format.ts +1 -1
- package/src/language-server/graphqlTypes.ts +13020 -3455
- package/src/language-server/index.ts +0 -1
- package/src/language-server/languageProvider.ts +29 -32
- package/src/language-server/loadingHandler.ts +10 -27
- package/src/language-server/project/base.ts +32 -25
- package/src/language-server/project/client.ts +80 -114
- package/src/language-server/project/defaultClientSchema.ts +29 -4
- package/src/language-server/providers/schema/__tests__/file.ts +60 -19
- package/src/language-server/providers/schema/base.ts +2 -2
- package/src/language-server/providers/schema/endpoint.ts +15 -34
- package/src/language-server/providers/schema/engine.ts +25 -18
- package/src/language-server/providers/schema/file.ts +41 -32
- package/src/language-server/providers/schema/index.ts +5 -21
- package/src/language-server/server.ts +72 -50
- package/src/language-server/typings/graphql.d.ts +3 -3
- package/src/language-server/utilities/__tests__/graphql.test.ts +42 -54
- package/src/language-server/utilities/debouncer.ts +1 -1
- package/src/language-server/utilities/debug.ts +6 -5
- package/src/language-server/utilities/graphql.ts +17 -16
- package/src/language-server/utilities/source.ts +16 -16
- package/src/language-server/utilities/uri.ts +2 -2
- package/src/language-server/workspace.ts +29 -37
- package/src/languageServerClient.ts +4 -4
- package/src/messages.ts +38 -47
- package/src/tools/__tests__/buildServiceDefinition.test.ts +2 -2
- package/src/tools/buildServiceDefinition.ts +11 -11
- package/src/tools/schema/resolveObject.ts +1 -1
- package/src/tools/utilities/predicates.ts +1 -1
- package/src/utils.ts +7 -6
- package/syntaxes/graphql.dart.json +2 -4
- package/syntaxes/graphql.ex.json +1 -4
- package/tsconfig.build.json +8 -1
- package/tsconfig.json +5 -3
- package/src/env/fetch/fetch.ts +0 -32
- package/src/env/fetch/global.ts +0 -30
- package/src/env/fetch/index.d.ts +0 -2
- package/src/env/fetch/index.ts +0 -2
- package/src/env/fetch/url.ts +0 -9
- package/src/env/polyfills/array.ts +0 -17
- package/src/env/polyfills/index.ts +0 -2
- package/src/env/polyfills/object.ts +0 -7
- package/src/language-server/engine/GraphQLDataSource.ts +0 -124
- package/src/language-server/project/service.ts +0 -48
- package/src/language-server/typings/codemirror.d.ts +0 -4
package/src/extension.ts
CHANGED
|
@@ -15,8 +15,13 @@ import {
|
|
|
15
15
|
} from "vscode";
|
|
16
16
|
import StatusBar from "./statusBar";
|
|
17
17
|
import { getLanguageServerClient } from "./languageServerClient";
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
18
|
+
import { LanguageClient } from "vscode-languageclient/node";
|
|
19
|
+
import {
|
|
20
|
+
type EngineDecoration,
|
|
21
|
+
LanguageServerCommands as LSCommands,
|
|
22
|
+
LanguageServerNotifications as LSNotifications,
|
|
23
|
+
LanguageServerRequests as LSRequests,
|
|
24
|
+
} from "./messages";
|
|
20
25
|
import {
|
|
21
26
|
printNoFileOpenMessage,
|
|
22
27
|
printStatsToClientOutputChannel,
|
|
@@ -25,8 +30,7 @@ import { Debug } from "./debug";
|
|
|
25
30
|
|
|
26
31
|
const { version } = require("../package.json");
|
|
27
32
|
|
|
28
|
-
let
|
|
29
|
-
let clientDisposable: Disposable;
|
|
33
|
+
let globalClient: LanguageClient | null = null;
|
|
30
34
|
let statusBar: StatusBar;
|
|
31
35
|
let outputChannel: OutputChannel;
|
|
32
36
|
let schemaTagItems: QuickPickItem[] = [];
|
|
@@ -44,86 +48,97 @@ function isError(response: any): response is ErrorShape {
|
|
|
44
48
|
);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
export
|
|
51
|
+
export interface VSCodeGraphQLExtension {
|
|
52
|
+
outputChannel: OutputChannel;
|
|
53
|
+
client: LanguageClient;
|
|
54
|
+
LanguageServerCommands: typeof LSCommands;
|
|
55
|
+
LanguageServerNotifications: typeof LSNotifications;
|
|
56
|
+
LanguageServerRequests: typeof LSRequests;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function activate(
|
|
60
|
+
context: ExtensionContext,
|
|
61
|
+
): Promise<VSCodeGraphQLExtension> {
|
|
48
62
|
const serverModule = context.asAbsolutePath(
|
|
49
|
-
join("lib/language-server", "server.js")
|
|
63
|
+
join("lib/language-server", "server.js"),
|
|
50
64
|
);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
outputChannel ||= window.createOutputChannel("Apollo GraphQL");
|
|
66
|
+
const client = getLanguageServerClient(serverModule, outputChannel);
|
|
67
|
+
globalClient = client;
|
|
54
68
|
client.registerProposedFeatures();
|
|
55
69
|
|
|
56
70
|
// Initialize disposables
|
|
57
71
|
statusBar = new StatusBar({
|
|
58
72
|
hasActiveTextEditor: Boolean(window.activeTextEditor),
|
|
59
73
|
});
|
|
60
|
-
outputChannel = window.createOutputChannel("Apollo GraphQL");
|
|
61
74
|
Debug.SetOutputConsole(outputChannel);
|
|
62
|
-
clientDisposable = client.start();
|
|
63
|
-
|
|
64
75
|
// Handoff disposables for cleanup
|
|
65
|
-
context.subscriptions.push(statusBar, outputChannel
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Debug.warning(message.message, message.stack);
|
|
84
|
-
break;
|
|
85
|
-
default:
|
|
86
|
-
Debug.info(message.message, message.stack);
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
});
|
|
76
|
+
context.subscriptions.push(statusBar, outputChannel);
|
|
77
|
+
|
|
78
|
+
client.onNotification(LSNotifications.ServerDebugMessage, (message) => {
|
|
79
|
+
switch (message.type) {
|
|
80
|
+
case "info":
|
|
81
|
+
Debug.info(message.message, message.stack);
|
|
82
|
+
break;
|
|
83
|
+
case "error":
|
|
84
|
+
Debug.error(message.message, message.stack);
|
|
85
|
+
break;
|
|
86
|
+
case "warning":
|
|
87
|
+
Debug.warning(message.message, message.stack);
|
|
88
|
+
break;
|
|
89
|
+
default:
|
|
90
|
+
Debug.info(message.message, message.stack);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
commands.registerCommand("apollographql/showStats", () => {
|
|
96
|
+
const fileUri = window.activeTextEditor
|
|
97
|
+
? window.activeTextEditor.document.uri.fsPath
|
|
98
|
+
: null;
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
// if no editor is open, but an output channel is, vscode returns something like
|
|
101
|
+
// output:extension-output-%234. If an editor IS open, this is something like file://Users/...
|
|
102
|
+
// This check is just for either a / or a \ anywhere in a fileUri
|
|
103
|
+
// TODO: this should probably be `registerTextEditorCommand` instead of `registerCommand`
|
|
104
|
+
const fileOpen = fileUri && /[\/\\]/.test(fileUri);
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
if (fileOpen) {
|
|
107
|
+
client.sendNotification(LSCommands.GetStats, {
|
|
108
|
+
uri: fileUri,
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
printNoFileOpenMessage(client, version);
|
|
113
|
+
client.outputChannel.show();
|
|
114
|
+
});
|
|
108
115
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
client.onNotification(LSNotifications.StatsLoaded, (params) => {
|
|
117
|
+
printStatsToClientOutputChannel(client, params, version);
|
|
118
|
+
client.outputChannel.show();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
commands.registerCommand("apollographql/fileStats", (uri: string) => {
|
|
122
|
+
// this has been introduced to check the LSP loading status in tests right now
|
|
123
|
+
// TODO: "apollographql/showStats" should use this request as well instead of notifications
|
|
124
|
+
return client.sendRequest(LSRequests.FileStats, { uri });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// For some reason, non-strings can only be sent in one direction. For now, messages
|
|
128
|
+
// coming from the language server just need to be stringified and parsed.
|
|
129
|
+
client.onNotification(LSNotifications.ConfigFilesFound, (params: string) => {
|
|
130
|
+
const response = JSON.parse(params) as Array<any> | ErrorShape;
|
|
131
|
+
|
|
132
|
+
const hasActiveTextEditor = Boolean(window.activeTextEditor);
|
|
133
|
+
if (Array.isArray(response)) {
|
|
134
|
+
const errors = response.filter((item) => isError(item));
|
|
135
|
+
if (errors.length) {
|
|
136
|
+
errors.forEach((response) => {
|
|
122
137
|
statusBar.showWarningState({
|
|
123
138
|
hasActiveTextEditor,
|
|
124
139
|
tooltip: "Configuration Error",
|
|
125
140
|
});
|
|
126
|
-
outputChannel.
|
|
141
|
+
outputChannel.appendLine("---\n" + response.stack + "\n---");
|
|
127
142
|
|
|
128
143
|
const infoButtonText = "More Info";
|
|
129
144
|
window
|
|
@@ -133,192 +148,203 @@ export function activate(context: ExtensionContext) {
|
|
|
133
148
|
outputChannel.show();
|
|
134
149
|
}
|
|
135
150
|
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
Debug.error(
|
|
147
|
-
`Invalid response type in message apollographql/configFilesFound:\n${JSON.stringify(
|
|
148
|
-
response
|
|
149
|
-
)}`
|
|
150
|
-
);
|
|
151
|
-
}
|
|
151
|
+
});
|
|
152
|
+
} else if (response.length === 0) {
|
|
153
|
+
statusBar.showWarningState({
|
|
154
|
+
hasActiveTextEditor,
|
|
155
|
+
tooltip: "No apollo.config.js file found",
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
statusBar.showLoadedState({ hasActiveTextEditor });
|
|
152
159
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
} else {
|
|
161
|
+
Debug.error(
|
|
162
|
+
`Invalid response type in message apollographql/configFilesFound:\n${JSON.stringify(
|
|
163
|
+
response,
|
|
164
|
+
)}`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
description: "",
|
|
169
|
-
detail: serviceID,
|
|
170
|
-
}));
|
|
171
|
-
|
|
172
|
-
schemaTagItems = [...items, ...schemaTagItems];
|
|
173
|
-
});
|
|
169
|
+
commands.registerCommand("apollographql/reloadService", () => {
|
|
170
|
+
// wipe out tags when reloading
|
|
171
|
+
// XXX we should clean up this handling
|
|
172
|
+
schemaTagItems = [];
|
|
173
|
+
client.sendNotification(LSCommands.ReloadService);
|
|
174
|
+
});
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
// For some reason, non-strings can only be sent in one direction. For now, messages
|
|
177
|
+
// coming from the language server just need to be stringified and parsed.
|
|
178
|
+
client.onNotification(LSNotifications.TagsLoaded, (params) => {
|
|
179
|
+
const [serviceID, tags]: [string, string[]] = JSON.parse(params);
|
|
180
|
+
const items = tags.map((tag) => ({
|
|
181
|
+
label: tag,
|
|
182
|
+
description: "",
|
|
183
|
+
detail: serviceID,
|
|
184
|
+
}));
|
|
185
|
+
|
|
186
|
+
schemaTagItems = [...items, ...schemaTagItems];
|
|
187
|
+
});
|
|
181
188
|
|
|
182
|
-
|
|
189
|
+
commands.registerCommand("apollographql/selectSchemaTag", async () => {
|
|
190
|
+
const selection = await window.showQuickPick(schemaTagItems);
|
|
191
|
+
if (selection) {
|
|
192
|
+
client.sendNotification(LSCommands.TagSelected, selection);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
183
195
|
|
|
184
|
-
|
|
185
|
-
statusBar.showLoadedState({
|
|
186
|
-
hasActiveTextEditor: Boolean(window.activeTextEditor),
|
|
187
|
-
});
|
|
188
|
-
const inMap = currentLoadingResolve.get(token);
|
|
189
|
-
if (inMap) {
|
|
190
|
-
inMap();
|
|
191
|
-
currentLoadingResolve.delete(token);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
196
|
+
let currentLoadingResolve: Map<number, () => void> = new Map();
|
|
194
197
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
location: ProgressLocation.Notification,
|
|
199
|
-
title: message,
|
|
200
|
-
cancellable: false,
|
|
201
|
-
},
|
|
202
|
-
() => {
|
|
203
|
-
return new Promise<void>((resolve) => {
|
|
204
|
-
currentLoadingResolve.set(token, resolve);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
);
|
|
198
|
+
client.onNotification(LSNotifications.LoadingComplete, (token) => {
|
|
199
|
+
statusBar.showLoadedState({
|
|
200
|
+
hasActiveTextEditor: Boolean(window.activeTextEditor),
|
|
208
201
|
});
|
|
202
|
+
const inMap = currentLoadingResolve.get(token);
|
|
203
|
+
if (inMap) {
|
|
204
|
+
inMap();
|
|
205
|
+
currentLoadingResolve.delete(token);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
209
208
|
|
|
210
|
-
|
|
211
|
-
|
|
209
|
+
client.onNotification(LSNotifications.Loading, ({ message, token }) => {
|
|
210
|
+
window.withProgress(
|
|
211
|
+
{
|
|
212
|
+
location: ProgressLocation.Notification,
|
|
213
|
+
title: message,
|
|
214
|
+
cancellable: false,
|
|
215
|
+
},
|
|
216
|
+
() => {
|
|
217
|
+
return new Promise<void>((resolve) => {
|
|
218
|
+
currentLoadingResolve.set(token, resolve);
|
|
219
|
+
});
|
|
220
|
+
},
|
|
212
221
|
);
|
|
222
|
+
});
|
|
213
223
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
224
|
+
const runIconOnDiskPath = Uri.file(
|
|
225
|
+
join(context.extensionPath, "images", "IconRun.svg"),
|
|
226
|
+
);
|
|
217
227
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
228
|
+
const textDecorationType = window.createTextEditorDecorationType({});
|
|
229
|
+
const runGlyphDecorationType = window.createTextEditorDecorationType({});
|
|
230
|
+
let latestDecorations: EngineDecoration[] | undefined = undefined;
|
|
221
231
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
window.activeTextEditor!.document.uri.toString()
|
|
226
|
-
);
|
|
232
|
+
const updateDecorations = () => {
|
|
233
|
+
if (window.activeTextEditor && latestDecorations) {
|
|
234
|
+
const editor = window.activeTextEditor!;
|
|
227
235
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
contentText: decoration.message,
|
|
239
|
-
textDecoration: "none; padding-left: 15px; opacity: .5",
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
};
|
|
236
|
+
const decorationsForDocument = latestDecorations.filter(
|
|
237
|
+
(decoration) =>
|
|
238
|
+
decoration.document ===
|
|
239
|
+
window.activeTextEditor!.document.uri.toString(),
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const textDecorations = decorationsForDocument.flatMap(
|
|
243
|
+
(decoration): DecorationOptions | DecorationOptions[] => {
|
|
244
|
+
if (decoration.type !== "text") {
|
|
245
|
+
return [];
|
|
243
246
|
}
|
|
244
|
-
);
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const hoverMessage =
|
|
253
|
-
decoration.hoverMessage === undefined
|
|
254
|
-
? undefined
|
|
255
|
-
: new MarkdownString(decoration.hoverMessage);
|
|
256
|
-
if (hoverMessage) {
|
|
257
|
-
hoverMessage.isTrusted = true;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const endOfLinePosition = editor.document.lineAt(
|
|
261
|
-
decoration.range.start.line
|
|
262
|
-
).range.end;
|
|
263
|
-
return {
|
|
264
|
-
// Hover range of just the end of the line (and the icon) so the hover shows above the icon,
|
|
265
|
-
// not over at the start of the line
|
|
266
|
-
range: new Range(endOfLinePosition, endOfLinePosition),
|
|
267
|
-
renderOptions: {
|
|
268
|
-
after: {
|
|
269
|
-
contentIconPath: runIconOnDiskPath,
|
|
270
|
-
textDecoration:
|
|
271
|
-
"none; border-radius: .20rem; margin-left: 8px; text-align: center;",
|
|
272
|
-
backgroundColor: "#2075D6",
|
|
273
|
-
width: "18px",
|
|
274
|
-
height: "18px",
|
|
275
|
-
},
|
|
248
|
+
return {
|
|
249
|
+
range: editor.document.lineAt(decoration.range.start.line).range,
|
|
250
|
+
renderOptions: {
|
|
251
|
+
after: {
|
|
252
|
+
contentText: decoration.message,
|
|
253
|
+
textDecoration: "none; padding-left: 15px; opacity: .5",
|
|
276
254
|
},
|
|
277
|
-
|
|
278
|
-
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const runGlyphDecorations = decorationsForDocument.flatMap(
|
|
261
|
+
(decoration): DecorationOptions | DecorationOptions[] => {
|
|
262
|
+
if (decoration.type !== "runGlyph") {
|
|
263
|
+
return [];
|
|
279
264
|
}
|
|
280
|
-
);
|
|
281
265
|
|
|
266
|
+
const hoverMessage =
|
|
267
|
+
decoration.hoverMessage === undefined
|
|
268
|
+
? undefined
|
|
269
|
+
: new MarkdownString(decoration.hoverMessage);
|
|
270
|
+
if (hoverMessage) {
|
|
271
|
+
hoverMessage.isTrusted = true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const endOfLinePosition = editor.document.lineAt(
|
|
275
|
+
decoration.range.start.line,
|
|
276
|
+
).range.end;
|
|
277
|
+
return {
|
|
278
|
+
// Hover range of just the end of the line (and the icon) so the hover shows above the icon,
|
|
279
|
+
// not over at the start of the line
|
|
280
|
+
range: new Range(endOfLinePosition, endOfLinePosition),
|
|
281
|
+
renderOptions: {
|
|
282
|
+
after: {
|
|
283
|
+
contentIconPath: runIconOnDiskPath,
|
|
284
|
+
textDecoration:
|
|
285
|
+
"none; border-radius: .20rem; margin-left: 8px; text-align: center;",
|
|
286
|
+
backgroundColor: "#2075D6",
|
|
287
|
+
width: "18px",
|
|
288
|
+
height: "18px",
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
hoverMessage,
|
|
292
|
+
};
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
window.activeTextEditor!.setDecorations(
|
|
297
|
+
textDecorationType,
|
|
298
|
+
textDecorations,
|
|
299
|
+
);
|
|
300
|
+
if (
|
|
301
|
+
workspace
|
|
302
|
+
.getConfiguration("apollographql")
|
|
303
|
+
.get("display.showRunInStudioButton")
|
|
304
|
+
) {
|
|
282
305
|
window.activeTextEditor!.setDecorations(
|
|
283
|
-
|
|
284
|
-
|
|
306
|
+
runGlyphDecorationType,
|
|
307
|
+
runGlyphDecorations,
|
|
285
308
|
);
|
|
286
|
-
if (
|
|
287
|
-
workspace
|
|
288
|
-
.getConfiguration("apollographql")
|
|
289
|
-
.get("display.showRunInStudioButton")
|
|
290
|
-
) {
|
|
291
|
-
window.activeTextEditor!.setDecorations(
|
|
292
|
-
runGlyphDecorationType,
|
|
293
|
-
runGlyphDecorations
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
309
|
}
|
|
297
|
-
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
298
312
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
updateDecorations();
|
|
304
|
-
}
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
window.onDidChangeActiveTextEditor(() => {
|
|
313
|
+
client.onNotification(
|
|
314
|
+
LSNotifications.EngineDecorations,
|
|
315
|
+
({ decorations }) => {
|
|
316
|
+
latestDecorations = decorations;
|
|
308
317
|
updateDecorations();
|
|
309
|
-
}
|
|
318
|
+
},
|
|
319
|
+
);
|
|
310
320
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
321
|
+
window.onDidChangeActiveTextEditor(() => {
|
|
322
|
+
updateDecorations();
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
workspace.registerTextDocumentContentProvider("graphql-schema", {
|
|
326
|
+
provideTextDocumentContent(uri: Uri) {
|
|
327
|
+
// the schema source is provided inside the URI, just return that here
|
|
328
|
+
return uri.query;
|
|
329
|
+
},
|
|
317
330
|
});
|
|
331
|
+
|
|
332
|
+
await client.start();
|
|
333
|
+
return {
|
|
334
|
+
outputChannel,
|
|
335
|
+
client,
|
|
336
|
+
LanguageServerCommands: LSCommands,
|
|
337
|
+
LanguageServerNotifications: LSNotifications,
|
|
338
|
+
LanguageServerRequests: LSRequests,
|
|
339
|
+
};
|
|
318
340
|
}
|
|
319
341
|
|
|
320
342
|
export function deactivate(): Thenable<void> | void {
|
|
321
|
-
if (
|
|
322
|
-
|
|
343
|
+
if (globalClient) {
|
|
344
|
+
try {
|
|
345
|
+
return globalClient.stop();
|
|
346
|
+
} finally {
|
|
347
|
+
globalClient = null;
|
|
348
|
+
}
|
|
323
349
|
}
|
|
324
350
|
}
|